]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
core: expose SyslogLevel and SyslogFacility as properties on dbus
[thirdparty/systemd.git] / src / core / dbus-execute.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/prctl.h>
23
24 #ifdef HAVE_SECCOMP
25 #include <seccomp.h>
26 #endif
27
28 #include "bus-util.h"
29 #include "missing.h"
30 #include "ioprio.h"
31 #include "strv.h"
32 #include "fileio.h"
33 #include "execute.h"
34 #include "capability.h"
35 #include "env-util.h"
36 #include "af-list.h"
37 #include "namespace.h"
38 #include "path-util.h"
39 #include "dbus-execute.h"
40
41 #ifdef HAVE_SECCOMP
42 #include "seccomp-util.h"
43 #endif
44
45 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
46
47 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
48
49 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
50
51 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
52 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
53
54 static int property_get_environment_files(
55 sd_bus *bus,
56 const char *path,
57 const char *interface,
58 const char *property,
59 sd_bus_message *reply,
60 void *userdata,
61 sd_bus_error *error) {
62
63 ExecContext *c = userdata;
64 char **j;
65 int r;
66
67 assert(bus);
68 assert(reply);
69 assert(c);
70
71 r = sd_bus_message_open_container(reply, 'a', "(sb)");
72 if (r < 0)
73 return r;
74
75 STRV_FOREACH(j, c->environment_files) {
76 const char *fn = *j;
77
78 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
79 if (r < 0)
80 return r;
81 }
82
83 return sd_bus_message_close_container(reply);
84 }
85
86 static int property_get_rlimit(
87 sd_bus *bus,
88 const char *path,
89 const char *interface,
90 const char *property,
91 sd_bus_message *reply,
92 void *userdata,
93 sd_bus_error *error) {
94
95 struct rlimit *rl;
96 uint64_t u;
97 rlim_t x;
98
99 assert(bus);
100 assert(reply);
101 assert(userdata);
102
103 rl = *(struct rlimit**) userdata;
104 if (rl)
105 x = rl->rlim_max;
106 else {
107 struct rlimit buf = {};
108 int z;
109
110 z = rlimit_from_string(property);
111 assert(z >= 0);
112
113 getrlimit(z, &buf);
114 x = buf.rlim_max;
115 }
116
117 /* rlim_t might have different sizes, let's map
118 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
119 * all archs */
120 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
121
122 return sd_bus_message_append(reply, "t", u);
123 }
124
125 static int property_get_oom_score_adjust(
126 sd_bus *bus,
127 const char *path,
128 const char *interface,
129 const char *property,
130 sd_bus_message *reply,
131 void *userdata,
132 sd_bus_error *error) {
133
134
135 ExecContext *c = userdata;
136 int32_t n;
137
138 assert(bus);
139 assert(reply);
140 assert(c);
141
142 if (c->oom_score_adjust_set)
143 n = c->oom_score_adjust;
144 else {
145 _cleanup_free_ char *t = NULL;
146
147 n = 0;
148 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
149 safe_atoi(t, &n);
150 }
151
152 return sd_bus_message_append(reply, "i", n);
153 }
154
155 static int property_get_nice(
156 sd_bus *bus,
157 const char *path,
158 const char *interface,
159 const char *property,
160 sd_bus_message *reply,
161 void *userdata,
162 sd_bus_error *error) {
163
164
165 ExecContext *c = userdata;
166 int32_t n;
167
168 assert(bus);
169 assert(reply);
170 assert(c);
171
172 if (c->nice_set)
173 n = c->nice;
174 else {
175 errno = 0;
176 n = getpriority(PRIO_PROCESS, 0);
177 if (errno != 0)
178 n = 0;
179 }
180
181 return sd_bus_message_append(reply, "i", n);
182 }
183
184 static int property_get_ioprio(
185 sd_bus *bus,
186 const char *path,
187 const char *interface,
188 const char *property,
189 sd_bus_message *reply,
190 void *userdata,
191 sd_bus_error *error) {
192
193
194 ExecContext *c = userdata;
195 int32_t n;
196
197 assert(bus);
198 assert(reply);
199 assert(c);
200
201 if (c->ioprio_set)
202 n = c->ioprio;
203 else {
204 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
205 if (n < 0)
206 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
207 }
208
209 return sd_bus_message_append(reply, "i", n);
210 }
211
212 static int property_get_cpu_sched_policy(
213 sd_bus *bus,
214 const char *path,
215 const char *interface,
216 const char *property,
217 sd_bus_message *reply,
218 void *userdata,
219 sd_bus_error *error) {
220
221 ExecContext *c = userdata;
222 int32_t n;
223
224 assert(bus);
225 assert(reply);
226 assert(c);
227
228 if (c->cpu_sched_set)
229 n = c->cpu_sched_policy;
230 else {
231 n = sched_getscheduler(0);
232 if (n < 0)
233 n = SCHED_OTHER;
234 }
235
236 return sd_bus_message_append(reply, "i", n);
237 }
238
239 static int property_get_cpu_sched_priority(
240 sd_bus *bus,
241 const char *path,
242 const char *interface,
243 const char *property,
244 sd_bus_message *reply,
245 void *userdata,
246 sd_bus_error *error) {
247
248 ExecContext *c = userdata;
249 int32_t n;
250
251 assert(bus);
252 assert(reply);
253 assert(c);
254
255 if (c->cpu_sched_set)
256 n = c->cpu_sched_priority;
257 else {
258 struct sched_param p = {};
259
260 if (sched_getparam(0, &p) >= 0)
261 n = p.sched_priority;
262 else
263 n = 0;
264 }
265
266 return sd_bus_message_append(reply, "i", n);
267 }
268
269 static int property_get_cpu_affinity(
270 sd_bus *bus,
271 const char *path,
272 const char *interface,
273 const char *property,
274 sd_bus_message *reply,
275 void *userdata,
276 sd_bus_error *error) {
277
278 ExecContext *c = userdata;
279
280 assert(bus);
281 assert(reply);
282 assert(c);
283
284 if (c->cpuset)
285 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
286 else
287 return sd_bus_message_append_array(reply, 'y', NULL, 0);
288 }
289
290 static int property_get_timer_slack_nsec(
291 sd_bus *bus,
292 const char *path,
293 const char *interface,
294 const char *property,
295 sd_bus_message *reply,
296 void *userdata,
297 sd_bus_error *error) {
298
299 ExecContext *c = userdata;
300 uint64_t u;
301
302 assert(bus);
303 assert(reply);
304 assert(c);
305
306 if (c->timer_slack_nsec != NSEC_INFINITY)
307 u = (uint64_t) c->timer_slack_nsec;
308 else
309 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
310
311 return sd_bus_message_append(reply, "t", u);
312 }
313
314 static int property_get_capability_bounding_set(
315 sd_bus *bus,
316 const char *path,
317 const char *interface,
318 const char *property,
319 sd_bus_message *reply,
320 void *userdata,
321 sd_bus_error *error) {
322
323 ExecContext *c = userdata;
324
325 assert(bus);
326 assert(reply);
327 assert(c);
328
329 /* We store this negated internally, to match the kernel, but
330 * we expose it normalized. */
331 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
332 }
333
334 static int property_get_capabilities(
335 sd_bus *bus,
336 const char *path,
337 const char *interface,
338 const char *property,
339 sd_bus_message *reply,
340 void *userdata,
341 sd_bus_error *error) {
342
343 ExecContext *c = userdata;
344 _cleanup_cap_free_charp_ char *t = NULL;
345 const char *s;
346
347 assert(bus);
348 assert(reply);
349 assert(c);
350
351 if (c->capabilities)
352 s = t = cap_to_text(c->capabilities, NULL);
353 else
354 s = "";
355
356 if (!s)
357 return -ENOMEM;
358
359 return sd_bus_message_append(reply, "s", s);
360 }
361
362 static int property_get_syscall_filter(
363 sd_bus *bus,
364 const char *path,
365 const char *interface,
366 const char *property,
367 sd_bus_message *reply,
368 void *userdata,
369 sd_bus_error *error) {
370
371 ExecContext *c = userdata;
372 _cleanup_strv_free_ char **l = NULL;
373 int r;
374
375 #ifdef HAVE_SECCOMP
376 Iterator i;
377 void *id;
378 #endif
379
380 assert(bus);
381 assert(reply);
382 assert(c);
383
384 r = sd_bus_message_open_container(reply, 'r', "bas");
385 if (r < 0)
386 return r;
387
388 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
389 if (r < 0)
390 return r;
391
392 #ifdef HAVE_SECCOMP
393 SET_FOREACH(id, c->syscall_filter, i) {
394 char *name;
395
396 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
397 if (!name)
398 continue;
399
400 r = strv_consume(&l, name);
401 if (r < 0)
402 return r;
403 }
404 #endif
405
406 strv_sort(l);
407
408 r = sd_bus_message_append_strv(reply, l);
409 if (r < 0)
410 return r;
411
412 return sd_bus_message_close_container(reply);
413 }
414
415 static int property_get_syscall_archs(
416 sd_bus *bus,
417 const char *path,
418 const char *interface,
419 const char *property,
420 sd_bus_message *reply,
421 void *userdata,
422 sd_bus_error *error) {
423
424 ExecContext *c = userdata;
425 _cleanup_strv_free_ char **l = NULL;
426 int r;
427
428 #ifdef HAVE_SECCOMP
429 Iterator i;
430 void *id;
431 #endif
432
433 assert(bus);
434 assert(reply);
435 assert(c);
436
437 #ifdef HAVE_SECCOMP
438 SET_FOREACH(id, c->syscall_archs, i) {
439 const char *name;
440
441 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
442 if (!name)
443 continue;
444
445 r = strv_extend(&l, name);
446 if (r < 0)
447 return -ENOMEM;
448 }
449 #endif
450
451 strv_sort(l);
452
453 r = sd_bus_message_append_strv(reply, l);
454 if (r < 0)
455 return r;
456
457 return 0;
458 }
459
460 static int property_get_syscall_errno(
461 sd_bus *bus,
462 const char *path,
463 const char *interface,
464 const char *property,
465 sd_bus_message *reply,
466 void *userdata,
467 sd_bus_error *error) {
468
469 ExecContext *c = userdata;
470
471 assert(bus);
472 assert(reply);
473 assert(c);
474
475 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
476 }
477
478 static int property_get_selinux_context(
479 sd_bus *bus,
480 const char *path,
481 const char *interface,
482 const char *property,
483 sd_bus_message *reply,
484 void *userdata,
485 sd_bus_error *error) {
486
487 ExecContext *c = userdata;
488
489 assert(bus);
490 assert(reply);
491 assert(c);
492
493 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
494 }
495
496 static int property_get_apparmor_profile(
497 sd_bus *bus,
498 const char *path,
499 const char *interface,
500 const char *property,
501 sd_bus_message *reply,
502 void *userdata,
503 sd_bus_error *error) {
504
505 ExecContext *c = userdata;
506
507 assert(bus);
508 assert(reply);
509 assert(c);
510
511 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
512 }
513
514 static int property_get_smack_process_label(
515 sd_bus *bus,
516 const char *path,
517 const char *interface,
518 const char *property,
519 sd_bus_message *reply,
520 void *userdata,
521 sd_bus_error *error) {
522
523 ExecContext *c = userdata;
524
525 assert(bus);
526 assert(reply);
527 assert(c);
528
529 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
530 }
531
532 static int property_get_personality(
533 sd_bus *bus,
534 const char *path,
535 const char *interface,
536 const char *property,
537 sd_bus_message *reply,
538 void *userdata,
539 sd_bus_error *error) {
540
541 ExecContext *c = userdata;
542
543 assert(bus);
544 assert(reply);
545 assert(c);
546
547 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
548 }
549
550 static int property_get_address_families(
551 sd_bus *bus,
552 const char *path,
553 const char *interface,
554 const char *property,
555 sd_bus_message *reply,
556 void *userdata,
557 sd_bus_error *error) {
558
559 ExecContext *c = userdata;
560 _cleanup_strv_free_ char **l = NULL;
561 Iterator i;
562 void *af;
563 int r;
564
565 assert(bus);
566 assert(reply);
567 assert(c);
568
569 r = sd_bus_message_open_container(reply, 'r', "bas");
570 if (r < 0)
571 return r;
572
573 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
574 if (r < 0)
575 return r;
576
577 SET_FOREACH(af, c->address_families, i) {
578 const char *name;
579
580 name = af_to_name(PTR_TO_INT(af));
581 if (!name)
582 continue;
583
584 r = strv_extend(&l, name);
585 if (r < 0)
586 return -ENOMEM;
587 }
588
589 strv_sort(l);
590
591 r = sd_bus_message_append_strv(reply, l);
592 if (r < 0)
593 return r;
594
595 return sd_bus_message_close_container(reply);
596 }
597
598 static int property_get_working_directory(
599 sd_bus *bus,
600 const char *path,
601 const char *interface,
602 const char *property,
603 sd_bus_message *reply,
604 void *userdata,
605 sd_bus_error *error) {
606
607 ExecContext *c = userdata;
608 const char *wd;
609
610 assert(bus);
611 assert(reply);
612 assert(c);
613
614 if (c->working_directory_home)
615 wd = "~";
616 else
617 wd = c->working_directory;
618
619 if (c->working_directory_missing_ok)
620 wd = strjoina("!", wd);
621
622 return sd_bus_message_append(reply, "s", wd);
623 }
624
625 static int property_get_syslog_level(
626 sd_bus *bus,
627 const char *path,
628 const char *interface,
629 const char *property,
630 sd_bus_message *reply,
631 void *userdata,
632 sd_bus_error *error) {
633
634 ExecContext *c = userdata;
635
636 assert(bus);
637 assert(reply);
638 assert(c);
639
640 return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
641 }
642
643 static int property_get_syslog_facility(
644 sd_bus *bus,
645 const char *path,
646 const char *interface,
647 const char *property,
648 sd_bus_message *reply,
649 void *userdata,
650 sd_bus_error *error) {
651
652 ExecContext *c = userdata;
653
654 assert(bus);
655 assert(reply);
656 assert(c);
657
658 return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
659 }
660
661 const sd_bus_vtable bus_exec_vtable[] = {
662 SD_BUS_VTABLE_START(0),
663 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
664 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
665 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
666 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
667 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
668 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
669 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
670 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
671 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
672 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
673 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
674 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
675 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
676 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
677 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
678 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
679 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
680 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
681 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
682 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
683 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
684 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
685 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
686 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
687 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
688 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
689 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
690 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
691 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
692 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
693 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
694 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
695 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
696 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
697 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
698 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
699 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
700 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
701 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
702 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
703 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
704 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
705 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
706 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
707 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
708 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
709 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
710 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
711 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
712 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
713 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
714 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
715 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
716 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
717 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
718 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
719 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
720 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
721 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
722 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
723 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
724 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
725 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
726 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
727 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
728 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
729 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
730 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
731 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
732 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
733 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
734 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
735 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
736 SD_BUS_VTABLE_END
737 };
738
739 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
740 int r;
741
742 assert(reply);
743 assert(c);
744
745 if (!c->path)
746 return 0;
747
748 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
749 if (r < 0)
750 return r;
751
752 r = sd_bus_message_append(reply, "s", c->path);
753 if (r < 0)
754 return r;
755
756 r = sd_bus_message_append_strv(reply, c->argv);
757 if (r < 0)
758 return r;
759
760 r = sd_bus_message_append(reply, "bttttuii",
761 c->ignore,
762 c->exec_status.start_timestamp.realtime,
763 c->exec_status.start_timestamp.monotonic,
764 c->exec_status.exit_timestamp.realtime,
765 c->exec_status.exit_timestamp.monotonic,
766 (uint32_t) c->exec_status.pid,
767 (int32_t) c->exec_status.code,
768 (int32_t) c->exec_status.status);
769 if (r < 0)
770 return r;
771
772 return sd_bus_message_close_container(reply);
773 }
774
775 int bus_property_get_exec_command(
776 sd_bus *bus,
777 const char *path,
778 const char *interface,
779 const char *property,
780 sd_bus_message *reply,
781 void *userdata,
782 sd_bus_error *ret_error) {
783
784 ExecCommand *c = (ExecCommand*) userdata;
785 int r;
786
787 assert(bus);
788 assert(reply);
789
790 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
791 if (r < 0)
792 return r;
793
794 r = append_exec_command(reply, c);
795 if (r < 0)
796 return r;
797
798 return sd_bus_message_close_container(reply);
799 }
800
801 int bus_property_get_exec_command_list(
802 sd_bus *bus,
803 const char *path,
804 const char *interface,
805 const char *property,
806 sd_bus_message *reply,
807 void *userdata,
808 sd_bus_error *ret_error) {
809
810 ExecCommand *c = *(ExecCommand**) userdata;
811 int r;
812
813 assert(bus);
814 assert(reply);
815
816 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
817 if (r < 0)
818 return r;
819
820 LIST_FOREACH(command, c, c) {
821 r = append_exec_command(reply, c);
822 if (r < 0)
823 return r;
824 }
825
826 return sd_bus_message_close_container(reply);
827 }
828
829 int bus_exec_context_set_transient_property(
830 Unit *u,
831 ExecContext *c,
832 const char *name,
833 sd_bus_message *message,
834 UnitSetPropertiesMode mode,
835 sd_bus_error *error) {
836
837 int r;
838
839 assert(u);
840 assert(c);
841 assert(name);
842 assert(message);
843
844 if (streq(name, "User")) {
845 const char *uu;
846
847 r = sd_bus_message_read(message, "s", &uu);
848 if (r < 0)
849 return r;
850
851 if (mode != UNIT_CHECK) {
852
853 if (isempty(uu)) {
854 c->user = mfree(c->user);
855 } else {
856 char *t;
857
858 t = strdup(uu);
859 if (!t)
860 return -ENOMEM;
861
862 free(c->user);
863 c->user = t;
864 }
865
866 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
867 }
868
869 return 1;
870
871 } else if (streq(name, "Group")) {
872 const char *gg;
873
874 r = sd_bus_message_read(message, "s", &gg);
875 if (r < 0)
876 return r;
877
878 if (mode != UNIT_CHECK) {
879
880 if (isempty(gg)) {
881 c->group = mfree(c->group);
882 } else {
883 char *t;
884
885 t = strdup(gg);
886 if (!t)
887 return -ENOMEM;
888
889 free(c->group);
890 c->group = t;
891 }
892
893 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
894 }
895
896 return 1;
897 } else if (streq(name, "SyslogIdentifier")) {
898 const char *id;
899
900 r = sd_bus_message_read(message, "s", &id);
901 if (r < 0)
902 return r;
903
904 if (mode != UNIT_CHECK) {
905
906 if (isempty(id)) {
907 c->syslog_identifier = mfree(c->syslog_identifier);
908 } else {
909 char *t;
910
911 t = strdup(id);
912 if (!t)
913 return -ENOMEM;
914
915 free(c->syslog_identifier);
916 c->syslog_identifier = t;
917 }
918
919 unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s\n", id);
920 }
921
922 return 1;
923 } else if (streq(name, "Nice")) {
924 int n;
925
926 r = sd_bus_message_read(message, "i", &n);
927 if (r < 0)
928 return r;
929
930 if (n < PRIO_MIN || n >= PRIO_MAX)
931 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
932
933 if (mode != UNIT_CHECK) {
934 c->nice = n;
935 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
936 }
937
938 return 1;
939
940 } else if (STR_IN_SET(name, "TTYPath", "RootDirectory")) {
941 const char *s;
942
943 r = sd_bus_message_read(message, "s", &s);
944 if (r < 0)
945 return r;
946
947 if (!path_is_absolute(s))
948 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
949
950 if (mode != UNIT_CHECK) {
951 if (streq(name, "TTYPath"))
952 r = free_and_strdup(&c->tty_path, s);
953 else {
954 assert(streq(name, "RootDirectory"));
955 r = free_and_strdup(&c->root_directory, s);
956 }
957 if (r < 0)
958 return r;
959
960 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
961 }
962
963 return 1;
964
965 } else if (streq(name, "WorkingDirectory")) {
966 const char *s;
967 bool missing_ok;
968
969 r = sd_bus_message_read(message, "s", &s);
970 if (r < 0)
971 return r;
972
973 if (s[0] == '-') {
974 missing_ok = true;
975 s++;
976 } else
977 missing_ok = false;
978
979 if (!streq(s, "~") && !path_is_absolute(s))
980 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
981
982 if (mode != UNIT_CHECK) {
983 if (streq(s, "~")) {
984 c->working_directory = mfree(c->working_directory);
985 c->working_directory_home = true;
986 } else {
987 r = free_and_strdup(&c->working_directory, s);
988 if (r < 0)
989 return r;
990
991 c->working_directory_home = false;
992 }
993
994 c->working_directory_missing_ok = missing_ok;
995 unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
996 }
997
998 return 1;
999
1000 } else if (streq(name, "StandardInput")) {
1001 const char *s;
1002 ExecInput p;
1003
1004 r = sd_bus_message_read(message, "s", &s);
1005 if (r < 0)
1006 return r;
1007
1008 p = exec_input_from_string(s);
1009 if (p < 0)
1010 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
1011
1012 if (mode != UNIT_CHECK) {
1013 c->std_input = p;
1014
1015 unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s\n", exec_input_to_string(p));
1016 }
1017
1018 return 1;
1019
1020
1021 } else if (streq(name, "StandardOutput")) {
1022 const char *s;
1023 ExecOutput p;
1024
1025 r = sd_bus_message_read(message, "s", &s);
1026 if (r < 0)
1027 return r;
1028
1029 p = exec_output_from_string(s);
1030 if (p < 0)
1031 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
1032
1033 if (mode != UNIT_CHECK) {
1034 c->std_output = p;
1035
1036 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s\n", exec_output_to_string(p));
1037 }
1038
1039 return 1;
1040
1041 } else if (streq(name, "StandardError")) {
1042 const char *s;
1043 ExecOutput p;
1044
1045 r = sd_bus_message_read(message, "s", &s);
1046 if (r < 0)
1047 return r;
1048
1049 p = exec_output_from_string(s);
1050 if (p < 0)
1051 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
1052
1053 if (mode != UNIT_CHECK) {
1054 c->std_error = p;
1055
1056 unit_write_drop_in_private_format(u, mode, name, "StandardError=%s\n", exec_output_to_string(p));
1057 }
1058
1059 return 1;
1060
1061 } else if (STR_IN_SET(name,
1062 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1063 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
1064 "NoNewPrivileges", "SyslogLevelPrefix")) {
1065 int b;
1066
1067 r = sd_bus_message_read(message, "b", &b);
1068 if (r < 0)
1069 return r;
1070
1071 if (mode != UNIT_CHECK) {
1072 if (streq(name, "IgnoreSIGPIPE"))
1073 c->ignore_sigpipe = b;
1074 else if (streq(name, "TTYVHangup"))
1075 c->tty_vhangup = b;
1076 else if (streq(name, "TTYReset"))
1077 c->tty_reset = b;
1078 else if (streq(name, "PrivateTmp"))
1079 c->private_tmp = b;
1080 else if (streq(name, "PrivateDevices"))
1081 c->private_devices = b;
1082 else if (streq(name, "PrivateNetwork"))
1083 c->private_network = b;
1084 else if (streq(name, "NoNewPrivileges"))
1085 c->no_new_privileges = b;
1086 else if (streq(name, "SyslogLevelPrefix"))
1087 c->syslog_level_prefix = b;
1088
1089 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, yes_no(b));
1090 }
1091
1092 return 1;
1093
1094 } else if (streq(name, "UtmpIdentifier")) {
1095 const char *id;
1096
1097 r = sd_bus_message_read(message, "s", &id);
1098 if (r < 0)
1099 return r;
1100
1101 if (mode != UNIT_CHECK) {
1102 if (isempty(id))
1103 c->utmp_id = mfree(c->utmp_id);
1104 else if (free_and_strdup(&c->utmp_id, id) < 0)
1105 return -ENOMEM;
1106
1107 unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s\n", strempty(id));
1108 }
1109
1110 return 1;
1111
1112 } else if (streq(name, "UtmpMode")) {
1113 const char *s;
1114 ExecUtmpMode m;
1115
1116 r = sd_bus_message_read(message, "s", &s);
1117 if (r < 0)
1118 return r;
1119
1120 m = exec_utmp_mode_from_string(s);
1121 if (m < 0)
1122 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
1123
1124 if (mode != UNIT_CHECK) {
1125 c->utmp_mode = m;
1126
1127 unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s\n", exec_utmp_mode_to_string(m));
1128 }
1129
1130 return 1;
1131
1132 } else if (streq(name, "PAMName")) {
1133 const char *n;
1134
1135 r = sd_bus_message_read(message, "s", &n);
1136 if (r < 0)
1137 return r;
1138
1139 if (mode != UNIT_CHECK) {
1140 if (isempty(n))
1141 c->pam_name = mfree(c->pam_name);
1142 else if (free_and_strdup(&c->pam_name, n) < 0)
1143 return -ENOMEM;
1144
1145 unit_write_drop_in_private_format(u, mode, name, "PAMName=%s\n", strempty(n));
1146 }
1147
1148 return 1;
1149
1150 } else if (streq(name, "Environment")) {
1151
1152 _cleanup_strv_free_ char **l = NULL;
1153
1154 r = sd_bus_message_read_strv(message, &l);
1155 if (r < 0)
1156 return r;
1157
1158 if (!strv_env_is_valid(l))
1159 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1160
1161 if (mode != UNIT_CHECK) {
1162 _cleanup_free_ char *joined = NULL;
1163 char **e;
1164
1165 e = strv_env_merge(2, c->environment, l);
1166 if (!e)
1167 return -ENOMEM;
1168
1169 strv_free(c->environment);
1170 c->environment = e;
1171
1172 joined = strv_join_quoted(c->environment);
1173 if (!joined)
1174 return -ENOMEM;
1175
1176 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
1177 }
1178
1179 return 1;
1180
1181 } else if (rlimit_from_string(name) >= 0) {
1182 uint64_t rl;
1183 rlim_t x;
1184
1185 r = sd_bus_message_read(message, "t", &rl);
1186 if (r < 0)
1187 return r;
1188
1189 if (rl == (uint64_t) -1)
1190 x = RLIM_INFINITY;
1191 else {
1192 x = (rlim_t) rl;
1193
1194 if ((uint64_t) x != rl)
1195 return -ERANGE;
1196 }
1197
1198 if (mode != UNIT_CHECK) {
1199 int z;
1200
1201 z = rlimit_from_string(name);
1202
1203 if (!c->rlimit[z]) {
1204 c->rlimit[z] = new(struct rlimit, 1);
1205 if (!c->rlimit[z])
1206 return -ENOMEM;
1207 }
1208
1209 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
1210
1211 if (x == RLIM_INFINITY)
1212 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
1213 else
1214 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
1215 }
1216
1217 return 1;
1218 }
1219
1220 return 0;
1221 }