]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
Hook more properties for transient units
[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 const sd_bus_vtable bus_exec_vtable[] = {
599 SD_BUS_VTABLE_START(0),
600 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
601 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
602 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
603 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
604 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
605 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
606 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
607 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
608 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
609 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
610 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
611 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
612 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
613 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
614 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
615 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
616 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
617 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
618 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
619 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
620 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
621 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
622 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
623 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
624 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
625 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
626 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
627 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
628 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
629 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
630 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
631 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
632 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
633 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
634 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
635 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
636 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
637 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
638 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
639 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
640 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
641 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
642 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
643 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
644 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
645 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
646 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
647 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
648 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
649 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
650 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
651 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
652 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
653 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
654 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
655 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
656 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
657 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
658 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
659 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
660 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
661 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
662 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
663 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
664 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
665 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
666 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
667 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
668 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
669 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
670 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
671 SD_BUS_VTABLE_END
672 };
673
674 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
675 int r;
676
677 assert(reply);
678 assert(c);
679
680 if (!c->path)
681 return 0;
682
683 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
684 if (r < 0)
685 return r;
686
687 r = sd_bus_message_append(reply, "s", c->path);
688 if (r < 0)
689 return r;
690
691 r = sd_bus_message_append_strv(reply, c->argv);
692 if (r < 0)
693 return r;
694
695 r = sd_bus_message_append(reply, "bttttuii",
696 c->ignore,
697 c->exec_status.start_timestamp.realtime,
698 c->exec_status.start_timestamp.monotonic,
699 c->exec_status.exit_timestamp.realtime,
700 c->exec_status.exit_timestamp.monotonic,
701 (uint32_t) c->exec_status.pid,
702 (int32_t) c->exec_status.code,
703 (int32_t) c->exec_status.status);
704 if (r < 0)
705 return r;
706
707 return sd_bus_message_close_container(reply);
708 }
709
710 int bus_property_get_exec_command(
711 sd_bus *bus,
712 const char *path,
713 const char *interface,
714 const char *property,
715 sd_bus_message *reply,
716 void *userdata,
717 sd_bus_error *ret_error) {
718
719 ExecCommand *c = (ExecCommand*) userdata;
720 int r;
721
722 assert(bus);
723 assert(reply);
724
725 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
726 if (r < 0)
727 return r;
728
729 r = append_exec_command(reply, c);
730 if (r < 0)
731 return r;
732
733 return sd_bus_message_close_container(reply);
734 }
735
736 int bus_property_get_exec_command_list(
737 sd_bus *bus,
738 const char *path,
739 const char *interface,
740 const char *property,
741 sd_bus_message *reply,
742 void *userdata,
743 sd_bus_error *ret_error) {
744
745 ExecCommand *c = *(ExecCommand**) userdata;
746 int r;
747
748 assert(bus);
749 assert(reply);
750
751 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
752 if (r < 0)
753 return r;
754
755 LIST_FOREACH(command, c, c) {
756 r = append_exec_command(reply, c);
757 if (r < 0)
758 return r;
759 }
760
761 return sd_bus_message_close_container(reply);
762 }
763
764 int bus_exec_context_set_transient_property(
765 Unit *u,
766 ExecContext *c,
767 const char *name,
768 sd_bus_message *message,
769 UnitSetPropertiesMode mode,
770 sd_bus_error *error) {
771
772 int r;
773
774 assert(u);
775 assert(c);
776 assert(name);
777 assert(message);
778
779 if (streq(name, "User")) {
780 const char *uu;
781
782 r = sd_bus_message_read(message, "s", &uu);
783 if (r < 0)
784 return r;
785
786 if (mode != UNIT_CHECK) {
787
788 if (isempty(uu)) {
789 c->user = mfree(c->user);
790 } else {
791 char *t;
792
793 t = strdup(uu);
794 if (!t)
795 return -ENOMEM;
796
797 free(c->user);
798 c->user = t;
799 }
800
801 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
802 }
803
804 return 1;
805
806 } else if (streq(name, "Group")) {
807 const char *gg;
808
809 r = sd_bus_message_read(message, "s", &gg);
810 if (r < 0)
811 return r;
812
813 if (mode != UNIT_CHECK) {
814
815 if (isempty(gg)) {
816 c->group = mfree(c->group);
817 } else {
818 char *t;
819
820 t = strdup(gg);
821 if (!t)
822 return -ENOMEM;
823
824 free(c->group);
825 c->group = t;
826 }
827
828 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
829 }
830
831 return 1;
832
833 } else if (streq(name, "Nice")) {
834 int n;
835
836 r = sd_bus_message_read(message, "i", &n);
837 if (r < 0)
838 return r;
839
840 if (n < PRIO_MIN || n >= PRIO_MAX)
841 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
842
843 if (mode != UNIT_CHECK) {
844 c->nice = n;
845 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
846 }
847
848 return 1;
849
850 } else if (STR_IN_SET(name,
851 "TTYPath", "WorkingDirectory", "RootDirectory")) {
852 const char *s;
853
854 r = sd_bus_message_read(message, "s", &s);
855 if (r < 0)
856 return r;
857
858 if (!path_is_absolute(s))
859 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
860
861 if (mode != UNIT_CHECK) {
862 char *t;
863
864 t = strdup(s);
865 if (!t)
866 return -ENOMEM;
867
868 if (streq(name, "TTYPath")) {
869 free(c->tty_path);
870 c->tty_path = t;
871 } else if (streq(name, "WorkingDirectory")) {
872 free(c->working_directory);
873 c->working_directory = t;
874 } else if (streq(name, "RootDirectory")) {
875 free(c->root_directory);
876 c->root_directory = t;
877 }
878
879 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
880 }
881
882 return 1;
883
884 } else if (streq(name, "StandardInput")) {
885 const char *s;
886 ExecInput p;
887
888 r = sd_bus_message_read(message, "s", &s);
889 if (r < 0)
890 return r;
891
892 p = exec_input_from_string(s);
893 if (p < 0)
894 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
895
896 if (mode != UNIT_CHECK) {
897 c->std_input = p;
898
899 unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s\n", exec_input_to_string(p));
900 }
901
902 return 1;
903
904
905 } else if (streq(name, "StandardOutput")) {
906 const char *s;
907 ExecOutput p;
908
909 r = sd_bus_message_read(message, "s", &s);
910 if (r < 0)
911 return r;
912
913 p = exec_output_from_string(s);
914 if (p < 0)
915 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
916
917 if (mode != UNIT_CHECK) {
918 c->std_output = p;
919
920 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s\n", exec_output_to_string(p));
921 }
922
923 return 1;
924
925 } else if (streq(name, "StandardError")) {
926 const char *s;
927 ExecOutput p;
928
929 r = sd_bus_message_read(message, "s", &s);
930 if (r < 0)
931 return r;
932
933 p = exec_output_from_string(s);
934 if (p < 0)
935 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
936
937 if (mode != UNIT_CHECK) {
938 c->std_error = p;
939
940 unit_write_drop_in_private_format(u, mode, name, "StandardError=%s\n", exec_output_to_string(p));
941 }
942
943 return 1;
944
945 } else if (STR_IN_SET(name,
946 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
947 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
948 "NoNewPrivileges")) {
949 int b;
950
951 r = sd_bus_message_read(message, "b", &b);
952 if (r < 0)
953 return r;
954
955 if (mode != UNIT_CHECK) {
956 if (streq(name, "IgnoreSIGPIPE"))
957 c->ignore_sigpipe = b;
958 else if (streq(name, "TTYVHangup"))
959 c->tty_vhangup = b;
960 else if (streq(name, "TTYReset"))
961 c->tty_reset = b;
962 else if (streq(name, "PrivateTmp"))
963 c->private_tmp = b;
964 else if (streq(name, "PrivateDevices"))
965 c->private_devices = b;
966 else if (streq(name, "PrivateNetwork"))
967 c->private_network = b;
968 else if (streq(name, "NoNewPrivileges"))
969 c->no_new_privileges = b;
970
971 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, yes_no(b));
972 }
973
974 return 1;
975
976 } else if (streq(name, "UtmpIdentifier")) {
977 const char *id;
978
979 r = sd_bus_message_read(message, "s", &id);
980 if (r < 0)
981 return r;
982
983 if (mode != UNIT_CHECK) {
984 if (isempty(id))
985 c->utmp_id = mfree(c->utmp_id);
986 else if (free_and_strdup(&c->utmp_id, id) < 0)
987 return -ENOMEM;
988
989 unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s\n", strempty(id));
990 }
991
992 return 1;
993
994 } else if (streq(name, "UtmpMode")) {
995 const char *s;
996 ExecUtmpMode m;
997
998 r = sd_bus_message_read(message, "s", &s);
999 if (r < 0)
1000 return r;
1001
1002 m = exec_utmp_mode_from_string(s);
1003 if (m < 0)
1004 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
1005
1006 if (mode != UNIT_CHECK) {
1007 c->utmp_mode = m;
1008
1009 unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s\n", exec_utmp_mode_to_string(m));
1010 }
1011
1012 return 1;
1013
1014 } else if (streq(name, "PAMName")) {
1015 const char *n;
1016
1017 r = sd_bus_message_read(message, "s", &n);
1018 if (r < 0)
1019 return r;
1020
1021 if (mode != UNIT_CHECK) {
1022 if (isempty(n))
1023 c->pam_name = mfree(c->pam_name);
1024 else if (free_and_strdup(&c->pam_name, n) < 0)
1025 return -ENOMEM;
1026
1027 unit_write_drop_in_private_format(u, mode, name, "PAMName=%s\n", strempty(n));
1028 }
1029
1030 return 1;
1031
1032 } else if (streq(name, "Environment")) {
1033
1034 _cleanup_strv_free_ char **l = NULL;
1035
1036 r = sd_bus_message_read_strv(message, &l);
1037 if (r < 0)
1038 return r;
1039
1040 if (!strv_env_is_valid(l))
1041 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1042
1043 if (mode != UNIT_CHECK) {
1044 _cleanup_free_ char *joined = NULL;
1045 char **e;
1046
1047 e = strv_env_merge(2, c->environment, l);
1048 if (!e)
1049 return -ENOMEM;
1050
1051 strv_free(c->environment);
1052 c->environment = e;
1053
1054 joined = strv_join_quoted(c->environment);
1055 if (!joined)
1056 return -ENOMEM;
1057
1058 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
1059 }
1060
1061 return 1;
1062
1063 } else if (rlimit_from_string(name) >= 0) {
1064 uint64_t rl;
1065 rlim_t x;
1066
1067 r = sd_bus_message_read(message, "t", &rl);
1068 if (r < 0)
1069 return r;
1070
1071 if (rl == (uint64_t) -1)
1072 x = RLIM_INFINITY;
1073 else {
1074 x = (rlim_t) rl;
1075
1076 if ((uint64_t) x != rl)
1077 return -ERANGE;
1078 }
1079
1080 if (mode != UNIT_CHECK) {
1081 int z;
1082
1083 z = rlimit_from_string(name);
1084
1085 if (!c->rlimit[z]) {
1086 c->rlimit[z] = new(struct rlimit, 1);
1087 if (!c->rlimit[z])
1088 return -ENOMEM;
1089 }
1090
1091 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
1092
1093 if (x == RLIM_INFINITY)
1094 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
1095 else
1096 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
1097 }
1098
1099 return 1;
1100 }
1101
1102 return 0;
1103 }