]> git.proxmox.com Git - systemd.git/blob - src/core/dbus-execute.c
Enable seccomp support on powerpc, ppc64el, and s390x
[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 "af-list.h"
29 #include "alloc-util.h"
30 #include "bus-util.h"
31 #include "capability-util.h"
32 #include "dbus-execute.h"
33 #include "env-util.h"
34 #include "execute.h"
35 #include "fd-util.h"
36 #include "fileio.h"
37 #include "ioprio.h"
38 #include "missing.h"
39 #include "namespace.h"
40 #include "parse-util.h"
41 #include "path-util.h"
42 #include "process-util.h"
43 #include "rlimit-util.h"
44 #ifdef HAVE_SECCOMP
45 #include "seccomp-util.h"
46 #endif
47 #include "strv.h"
48 #include "syslog-util.h"
49 #include "utf8.h"
50
51 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
52
53 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
54
55 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
56
57 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
58 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
59
60 static int property_get_environment_files(
61 sd_bus *bus,
62 const char *path,
63 const char *interface,
64 const char *property,
65 sd_bus_message *reply,
66 void *userdata,
67 sd_bus_error *error) {
68
69 ExecContext *c = userdata;
70 char **j;
71 int r;
72
73 assert(bus);
74 assert(reply);
75 assert(c);
76
77 r = sd_bus_message_open_container(reply, 'a', "(sb)");
78 if (r < 0)
79 return r;
80
81 STRV_FOREACH(j, c->environment_files) {
82 const char *fn = *j;
83
84 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
85 if (r < 0)
86 return r;
87 }
88
89 return sd_bus_message_close_container(reply);
90 }
91
92 static int property_get_oom_score_adjust(
93 sd_bus *bus,
94 const char *path,
95 const char *interface,
96 const char *property,
97 sd_bus_message *reply,
98 void *userdata,
99 sd_bus_error *error) {
100
101
102 ExecContext *c = userdata;
103 int32_t n;
104
105 assert(bus);
106 assert(reply);
107 assert(c);
108
109 if (c->oom_score_adjust_set)
110 n = c->oom_score_adjust;
111 else {
112 _cleanup_free_ char *t = NULL;
113
114 n = 0;
115 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
116 safe_atoi32(t, &n);
117 }
118
119 return sd_bus_message_append(reply, "i", n);
120 }
121
122 static int property_get_nice(
123 sd_bus *bus,
124 const char *path,
125 const char *interface,
126 const char *property,
127 sd_bus_message *reply,
128 void *userdata,
129 sd_bus_error *error) {
130
131
132 ExecContext *c = userdata;
133 int32_t n;
134
135 assert(bus);
136 assert(reply);
137 assert(c);
138
139 if (c->nice_set)
140 n = c->nice;
141 else {
142 errno = 0;
143 n = getpriority(PRIO_PROCESS, 0);
144 if (errno != 0)
145 n = 0;
146 }
147
148 return sd_bus_message_append(reply, "i", n);
149 }
150
151 static int property_get_ioprio(
152 sd_bus *bus,
153 const char *path,
154 const char *interface,
155 const char *property,
156 sd_bus_message *reply,
157 void *userdata,
158 sd_bus_error *error) {
159
160
161 ExecContext *c = userdata;
162 int32_t n;
163
164 assert(bus);
165 assert(reply);
166 assert(c);
167
168 if (c->ioprio_set)
169 n = c->ioprio;
170 else {
171 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
172 if (n < 0)
173 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
174 }
175
176 return sd_bus_message_append(reply, "i", n);
177 }
178
179 static int property_get_cpu_sched_policy(
180 sd_bus *bus,
181 const char *path,
182 const char *interface,
183 const char *property,
184 sd_bus_message *reply,
185 void *userdata,
186 sd_bus_error *error) {
187
188 ExecContext *c = userdata;
189 int32_t n;
190
191 assert(bus);
192 assert(reply);
193 assert(c);
194
195 if (c->cpu_sched_set)
196 n = c->cpu_sched_policy;
197 else {
198 n = sched_getscheduler(0);
199 if (n < 0)
200 n = SCHED_OTHER;
201 }
202
203 return sd_bus_message_append(reply, "i", n);
204 }
205
206 static int property_get_cpu_sched_priority(
207 sd_bus *bus,
208 const char *path,
209 const char *interface,
210 const char *property,
211 sd_bus_message *reply,
212 void *userdata,
213 sd_bus_error *error) {
214
215 ExecContext *c = userdata;
216 int32_t n;
217
218 assert(bus);
219 assert(reply);
220 assert(c);
221
222 if (c->cpu_sched_set)
223 n = c->cpu_sched_priority;
224 else {
225 struct sched_param p = {};
226
227 if (sched_getparam(0, &p) >= 0)
228 n = p.sched_priority;
229 else
230 n = 0;
231 }
232
233 return sd_bus_message_append(reply, "i", n);
234 }
235
236 static int property_get_cpu_affinity(
237 sd_bus *bus,
238 const char *path,
239 const char *interface,
240 const char *property,
241 sd_bus_message *reply,
242 void *userdata,
243 sd_bus_error *error) {
244
245 ExecContext *c = userdata;
246
247 assert(bus);
248 assert(reply);
249 assert(c);
250
251 if (c->cpuset)
252 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
253 else
254 return sd_bus_message_append_array(reply, 'y', NULL, 0);
255 }
256
257 static int property_get_timer_slack_nsec(
258 sd_bus *bus,
259 const char *path,
260 const char *interface,
261 const char *property,
262 sd_bus_message *reply,
263 void *userdata,
264 sd_bus_error *error) {
265
266 ExecContext *c = userdata;
267 uint64_t u;
268
269 assert(bus);
270 assert(reply);
271 assert(c);
272
273 if (c->timer_slack_nsec != NSEC_INFINITY)
274 u = (uint64_t) c->timer_slack_nsec;
275 else
276 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
277
278 return sd_bus_message_append(reply, "t", u);
279 }
280
281 static int property_get_capability_bounding_set(
282 sd_bus *bus,
283 const char *path,
284 const char *interface,
285 const char *property,
286 sd_bus_message *reply,
287 void *userdata,
288 sd_bus_error *error) {
289
290 ExecContext *c = userdata;
291
292 assert(bus);
293 assert(reply);
294 assert(c);
295
296 /* We store this negated internally, to match the kernel, but
297 * we expose it normalized. */
298 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
299 }
300
301 static int property_get_capabilities(
302 sd_bus *bus,
303 const char *path,
304 const char *interface,
305 const char *property,
306 sd_bus_message *reply,
307 void *userdata,
308 sd_bus_error *error) {
309
310 ExecContext *c = userdata;
311 _cleanup_cap_free_charp_ char *t = NULL;
312 const char *s;
313
314 assert(bus);
315 assert(reply);
316 assert(c);
317
318 if (c->capabilities)
319 s = t = cap_to_text(c->capabilities, NULL);
320 else
321 s = "";
322
323 if (!s)
324 return -ENOMEM;
325
326 return sd_bus_message_append(reply, "s", s);
327 }
328
329 static int property_get_syscall_filter(
330 sd_bus *bus,
331 const char *path,
332 const char *interface,
333 const char *property,
334 sd_bus_message *reply,
335 void *userdata,
336 sd_bus_error *error) {
337
338 ExecContext *c = userdata;
339 _cleanup_strv_free_ char **l = NULL;
340 int r;
341
342 #ifdef HAVE_SECCOMP
343 Iterator i;
344 void *id;
345 #endif
346
347 assert(bus);
348 assert(reply);
349 assert(c);
350
351 r = sd_bus_message_open_container(reply, 'r', "bas");
352 if (r < 0)
353 return r;
354
355 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
356 if (r < 0)
357 return r;
358
359 #ifdef HAVE_SECCOMP
360 SET_FOREACH(id, c->syscall_filter, i) {
361 char *name;
362
363 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
364 if (!name)
365 continue;
366
367 r = strv_consume(&l, name);
368 if (r < 0)
369 return r;
370 }
371 #endif
372
373 strv_sort(l);
374
375 r = sd_bus_message_append_strv(reply, l);
376 if (r < 0)
377 return r;
378
379 return sd_bus_message_close_container(reply);
380 }
381
382 static int property_get_syscall_archs(
383 sd_bus *bus,
384 const char *path,
385 const char *interface,
386 const char *property,
387 sd_bus_message *reply,
388 void *userdata,
389 sd_bus_error *error) {
390
391 ExecContext *c = userdata;
392 _cleanup_strv_free_ char **l = NULL;
393 int r;
394
395 #ifdef HAVE_SECCOMP
396 Iterator i;
397 void *id;
398 #endif
399
400 assert(bus);
401 assert(reply);
402 assert(c);
403
404 #ifdef HAVE_SECCOMP
405 SET_FOREACH(id, c->syscall_archs, i) {
406 const char *name;
407
408 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
409 if (!name)
410 continue;
411
412 r = strv_extend(&l, name);
413 if (r < 0)
414 return -ENOMEM;
415 }
416 #endif
417
418 strv_sort(l);
419
420 r = sd_bus_message_append_strv(reply, l);
421 if (r < 0)
422 return r;
423
424 return 0;
425 }
426
427 static int property_get_syscall_errno(
428 sd_bus *bus,
429 const char *path,
430 const char *interface,
431 const char *property,
432 sd_bus_message *reply,
433 void *userdata,
434 sd_bus_error *error) {
435
436 ExecContext *c = userdata;
437
438 assert(bus);
439 assert(reply);
440 assert(c);
441
442 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
443 }
444
445 static int property_get_selinux_context(
446 sd_bus *bus,
447 const char *path,
448 const char *interface,
449 const char *property,
450 sd_bus_message *reply,
451 void *userdata,
452 sd_bus_error *error) {
453
454 ExecContext *c = userdata;
455
456 assert(bus);
457 assert(reply);
458 assert(c);
459
460 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
461 }
462
463 static int property_get_apparmor_profile(
464 sd_bus *bus,
465 const char *path,
466 const char *interface,
467 const char *property,
468 sd_bus_message *reply,
469 void *userdata,
470 sd_bus_error *error) {
471
472 ExecContext *c = userdata;
473
474 assert(bus);
475 assert(reply);
476 assert(c);
477
478 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
479 }
480
481 static int property_get_smack_process_label(
482 sd_bus *bus,
483 const char *path,
484 const char *interface,
485 const char *property,
486 sd_bus_message *reply,
487 void *userdata,
488 sd_bus_error *error) {
489
490 ExecContext *c = userdata;
491
492 assert(bus);
493 assert(reply);
494 assert(c);
495
496 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
497 }
498
499 static int property_get_personality(
500 sd_bus *bus,
501 const char *path,
502 const char *interface,
503 const char *property,
504 sd_bus_message *reply,
505 void *userdata,
506 sd_bus_error *error) {
507
508 ExecContext *c = userdata;
509
510 assert(bus);
511 assert(reply);
512 assert(c);
513
514 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
515 }
516
517 static int property_get_address_families(
518 sd_bus *bus,
519 const char *path,
520 const char *interface,
521 const char *property,
522 sd_bus_message *reply,
523 void *userdata,
524 sd_bus_error *error) {
525
526 ExecContext *c = userdata;
527 _cleanup_strv_free_ char **l = NULL;
528 Iterator i;
529 void *af;
530 int r;
531
532 assert(bus);
533 assert(reply);
534 assert(c);
535
536 r = sd_bus_message_open_container(reply, 'r', "bas");
537 if (r < 0)
538 return r;
539
540 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
541 if (r < 0)
542 return r;
543
544 SET_FOREACH(af, c->address_families, i) {
545 const char *name;
546
547 name = af_to_name(PTR_TO_INT(af));
548 if (!name)
549 continue;
550
551 r = strv_extend(&l, name);
552 if (r < 0)
553 return -ENOMEM;
554 }
555
556 strv_sort(l);
557
558 r = sd_bus_message_append_strv(reply, l);
559 if (r < 0)
560 return r;
561
562 return sd_bus_message_close_container(reply);
563 }
564
565 static int property_get_working_directory(
566 sd_bus *bus,
567 const char *path,
568 const char *interface,
569 const char *property,
570 sd_bus_message *reply,
571 void *userdata,
572 sd_bus_error *error) {
573
574 ExecContext *c = userdata;
575 const char *wd;
576
577 assert(bus);
578 assert(reply);
579 assert(c);
580
581 if (c->working_directory_home)
582 wd = "~";
583 else
584 wd = c->working_directory;
585
586 if (c->working_directory_missing_ok)
587 wd = strjoina("!", wd);
588
589 return sd_bus_message_append(reply, "s", wd);
590 }
591
592 static int property_get_syslog_level(
593 sd_bus *bus,
594 const char *path,
595 const char *interface,
596 const char *property,
597 sd_bus_message *reply,
598 void *userdata,
599 sd_bus_error *error) {
600
601 ExecContext *c = userdata;
602
603 assert(bus);
604 assert(reply);
605 assert(c);
606
607 return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
608 }
609
610 static int property_get_syslog_facility(
611 sd_bus *bus,
612 const char *path,
613 const char *interface,
614 const char *property,
615 sd_bus_message *reply,
616 void *userdata,
617 sd_bus_error *error) {
618
619 ExecContext *c = userdata;
620
621 assert(bus);
622 assert(reply);
623 assert(c);
624
625 return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
626 }
627
628 const sd_bus_vtable bus_exec_vtable[] = {
629 SD_BUS_VTABLE_START(0),
630 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
631 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
632 SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
633 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
634 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
635 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
636 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
637 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
638 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
639 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
640 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
641 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
642 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
643 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
644 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
645 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
646 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
647 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
648 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
649 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
650 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
651 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
652 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
653 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
654 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
655 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
656 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
657 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
658 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
659 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
660 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
661 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
662 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
663 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
664 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
665 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
666 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
667 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
668 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
669 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
670 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
671 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
672 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
673 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
674 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
675 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
676 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
677 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
678 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
679 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
680 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
681 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
682 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
683 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
684 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
685 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
686 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
687 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
688 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
689 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
690 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
691 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
692 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
693 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
694 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
695 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
696 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
697 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
698 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
699 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
700 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
701 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
702 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
703 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
704 SD_BUS_VTABLE_END
705 };
706
707 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
708 int r;
709
710 assert(reply);
711 assert(c);
712
713 if (!c->path)
714 return 0;
715
716 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
717 if (r < 0)
718 return r;
719
720 r = sd_bus_message_append(reply, "s", c->path);
721 if (r < 0)
722 return r;
723
724 r = sd_bus_message_append_strv(reply, c->argv);
725 if (r < 0)
726 return r;
727
728 r = sd_bus_message_append(reply, "bttttuii",
729 c->ignore,
730 c->exec_status.start_timestamp.realtime,
731 c->exec_status.start_timestamp.monotonic,
732 c->exec_status.exit_timestamp.realtime,
733 c->exec_status.exit_timestamp.monotonic,
734 (uint32_t) c->exec_status.pid,
735 (int32_t) c->exec_status.code,
736 (int32_t) c->exec_status.status);
737 if (r < 0)
738 return r;
739
740 return sd_bus_message_close_container(reply);
741 }
742
743 int bus_property_get_exec_command(
744 sd_bus *bus,
745 const char *path,
746 const char *interface,
747 const char *property,
748 sd_bus_message *reply,
749 void *userdata,
750 sd_bus_error *ret_error) {
751
752 ExecCommand *c = (ExecCommand*) userdata;
753 int r;
754
755 assert(bus);
756 assert(reply);
757
758 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
759 if (r < 0)
760 return r;
761
762 r = append_exec_command(reply, c);
763 if (r < 0)
764 return r;
765
766 return sd_bus_message_close_container(reply);
767 }
768
769 int bus_property_get_exec_command_list(
770 sd_bus *bus,
771 const char *path,
772 const char *interface,
773 const char *property,
774 sd_bus_message *reply,
775 void *userdata,
776 sd_bus_error *ret_error) {
777
778 ExecCommand *c = *(ExecCommand**) userdata;
779 int r;
780
781 assert(bus);
782 assert(reply);
783
784 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
785 if (r < 0)
786 return r;
787
788 LIST_FOREACH(command, c, c) {
789 r = append_exec_command(reply, c);
790 if (r < 0)
791 return r;
792 }
793
794 return sd_bus_message_close_container(reply);
795 }
796
797 int bus_exec_context_set_transient_property(
798 Unit *u,
799 ExecContext *c,
800 const char *name,
801 sd_bus_message *message,
802 UnitSetPropertiesMode mode,
803 sd_bus_error *error) {
804
805 int r;
806
807 assert(u);
808 assert(c);
809 assert(name);
810 assert(message);
811
812 if (streq(name, "User")) {
813 const char *uu;
814
815 r = sd_bus_message_read(message, "s", &uu);
816 if (r < 0)
817 return r;
818
819 if (mode != UNIT_CHECK) {
820
821 if (isempty(uu)) {
822 c->user = mfree(c->user);
823 } else {
824 char *t;
825
826 t = strdup(uu);
827 if (!t)
828 return -ENOMEM;
829
830 free(c->user);
831 c->user = t;
832 }
833
834 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
835 }
836
837 return 1;
838
839 } else if (streq(name, "Group")) {
840 const char *gg;
841
842 r = sd_bus_message_read(message, "s", &gg);
843 if (r < 0)
844 return r;
845
846 if (mode != UNIT_CHECK) {
847
848 if (isempty(gg)) {
849 c->group = mfree(c->group);
850 } else {
851 char *t;
852
853 t = strdup(gg);
854 if (!t)
855 return -ENOMEM;
856
857 free(c->group);
858 c->group = t;
859 }
860
861 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
862 }
863
864 return 1;
865 } else if (streq(name, "SyslogIdentifier")) {
866 const char *id;
867
868 r = sd_bus_message_read(message, "s", &id);
869 if (r < 0)
870 return r;
871
872 if (mode != UNIT_CHECK) {
873
874 if (isempty(id)) {
875 c->syslog_identifier = mfree(c->syslog_identifier);
876 } else {
877 char *t;
878
879 t = strdup(id);
880 if (!t)
881 return -ENOMEM;
882
883 free(c->syslog_identifier);
884 c->syslog_identifier = t;
885 }
886
887 unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s\n", id);
888 }
889
890 return 1;
891 } else if (streq(name, "SyslogLevel")) {
892 int level;
893
894 r = sd_bus_message_read(message, "i", &level);
895 if (r < 0)
896 return r;
897
898 if (!log_level_is_valid(level))
899 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
900
901 if (mode != UNIT_CHECK) {
902 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
903 unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i\n", level);
904 }
905
906 return 1;
907 } else if (streq(name, "SyslogFacility")) {
908 int facility;
909
910 r = sd_bus_message_read(message, "i", &facility);
911 if (r < 0)
912 return r;
913
914 if (!log_facility_unshifted_is_valid(facility))
915 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
916
917 if (mode != UNIT_CHECK) {
918 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
919 unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i\n", facility);
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 if (strv_length(l) == 0) {
1166 c->environment = strv_free(c->environment);
1167 unit_write_drop_in_private_format(u, mode, name, "Environment=\n");
1168 } else {
1169 e = strv_env_merge(2, c->environment, l);
1170 if (!e)
1171 return -ENOMEM;
1172
1173 strv_free(c->environment);
1174 c->environment = e;
1175
1176 joined = strv_join_quoted(c->environment);
1177 if (!joined)
1178 return -ENOMEM;
1179
1180 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
1181 }
1182 }
1183
1184 return 1;
1185
1186 } else if (streq(name, "TimerSlackNSec")) {
1187
1188 nsec_t n;
1189
1190 r = sd_bus_message_read(message, "t", &n);
1191 if (r < 0)
1192 return r;
1193
1194 if (mode != UNIT_CHECK) {
1195 c->timer_slack_nsec = n;
1196 unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT "\n", n);
1197 }
1198
1199 return 1;
1200
1201 } else if (streq(name, "OOMScoreAdjust")) {
1202 int oa;
1203
1204 r = sd_bus_message_read(message, "i", &oa);
1205 if (r < 0)
1206 return r;
1207
1208 if (!oom_score_adjust_is_valid(oa))
1209 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
1210
1211 if (mode != UNIT_CHECK) {
1212 c->oom_score_adjust = oa;
1213 c->oom_score_adjust_set = true;
1214 unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i\n", oa);
1215 }
1216
1217 return 1;
1218
1219 } else if (streq(name, "EnvironmentFiles")) {
1220
1221 _cleanup_free_ char *joined = NULL;
1222 _cleanup_fclose_ FILE *f = NULL;
1223 _cleanup_free_ char **l = NULL;
1224 size_t size = 0;
1225 char **i;
1226
1227 r = sd_bus_message_enter_container(message, 'a', "(sb)");
1228 if (r < 0)
1229 return r;
1230
1231 f = open_memstream(&joined, &size);
1232 if (!f)
1233 return -ENOMEM;
1234
1235 STRV_FOREACH(i, c->environment_files)
1236 fprintf(f, "EnvironmentFile=%s\n", *i);
1237
1238 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
1239 const char *path;
1240 int b;
1241
1242 r = sd_bus_message_read(message, "sb", &path, &b);
1243 if (r < 0)
1244 return r;
1245
1246 r = sd_bus_message_exit_container(message);
1247 if (r < 0)
1248 return r;
1249
1250 if (!isempty(path) && !path_is_absolute(path))
1251 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
1252
1253 if (mode != UNIT_CHECK) {
1254 char *buf = NULL;
1255
1256 buf = strjoin(b ? "-" : "", path, NULL);
1257 if (!buf)
1258 return -ENOMEM;
1259
1260 fprintf(f, "EnvironmentFile=%s\n", buf);
1261
1262 r = strv_consume(&l, buf);
1263 if (r < 0)
1264 return r;
1265 }
1266 }
1267 if (r < 0)
1268 return r;
1269
1270 r = sd_bus_message_exit_container(message);
1271 if (r < 0)
1272 return r;
1273
1274 r = fflush_and_check(f);
1275 if (r < 0)
1276 return r;
1277
1278 if (mode != UNIT_CHECK) {
1279 if (strv_isempty(l)) {
1280 c->environment_files = strv_free(c->environment_files);
1281 unit_write_drop_in_private(u, mode, name, "EnvironmentFile=\n");
1282 } else {
1283 r = strv_extend_strv(&c->environment_files, l, true);
1284 if (r < 0)
1285 return r;
1286
1287 unit_write_drop_in_private(u, mode, name, joined);
1288 }
1289 }
1290
1291 return 1;
1292
1293 } else if (streq(name, "PassEnvironment")) {
1294
1295 _cleanup_strv_free_ char **l = NULL;
1296
1297 r = sd_bus_message_read_strv(message, &l);
1298 if (r < 0)
1299 return r;
1300
1301 if (!strv_env_name_is_valid(l))
1302 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment block.");
1303
1304 if (mode != UNIT_CHECK) {
1305 if (strv_isempty(l)) {
1306 c->pass_environment = strv_free(c->pass_environment);
1307 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=\n");
1308 } else {
1309 _cleanup_free_ char *joined = NULL;
1310
1311 r = strv_extend_strv(&c->pass_environment, l, true);
1312 if (r < 0)
1313 return r;
1314
1315 joined = strv_join_quoted(c->pass_environment);
1316 if (!joined)
1317 return -ENOMEM;
1318
1319 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=%s\n", joined);
1320 }
1321 }
1322
1323 return 1;
1324
1325 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1326
1327 _cleanup_strv_free_ char **l = NULL;
1328 char ***dirs;
1329 char **p;
1330
1331 r = sd_bus_message_read_strv(message, &l);
1332 if (r < 0)
1333 return r;
1334
1335 STRV_FOREACH(p, l) {
1336 int offset;
1337 if (!utf8_is_valid(*p))
1338 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1339
1340 offset = **p == '-';
1341 if (!path_is_absolute(*p + offset))
1342 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1343 }
1344
1345 if (mode != UNIT_CHECK) {
1346 _cleanup_free_ char *joined = NULL;
1347
1348 if (streq(name, "ReadWriteDirectories"))
1349 dirs = &c->read_write_dirs;
1350 else if (streq(name, "ReadOnlyDirectories"))
1351 dirs = &c->read_only_dirs;
1352 else if (streq(name, "InaccessibleDirectories"))
1353 dirs = &c->inaccessible_dirs;
1354
1355 if (strv_length(l) == 0) {
1356 *dirs = strv_free(*dirs);
1357 unit_write_drop_in_private_format(u, mode, name, "%s=\n", name);
1358 } else {
1359 r = strv_extend_strv(dirs, l, true);
1360
1361 if (r < 0)
1362 return -ENOMEM;
1363
1364 joined = strv_join_quoted(*dirs);
1365 if (!joined)
1366 return -ENOMEM;
1367
1368 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, joined);
1369 }
1370
1371 }
1372
1373 return 1;
1374
1375 } else if (streq(name, "ProtectSystem")) {
1376 const char *s;
1377 ProtectSystem ps;
1378
1379 r = sd_bus_message_read(message, "s", &s);
1380 if (r < 0)
1381 return r;
1382
1383 r = parse_boolean(s);
1384 if (r > 0)
1385 ps = PROTECT_SYSTEM_YES;
1386 else if (r == 0)
1387 ps = PROTECT_SYSTEM_NO;
1388 else {
1389 ps = protect_system_from_string(s);
1390 if (ps < 0)
1391 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value");
1392 }
1393
1394 if (mode != UNIT_CHECK) {
1395 c->protect_system = ps;
1396 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
1397 }
1398
1399 return 1;
1400
1401 } else if (streq(name, "ProtectHome")) {
1402 const char *s;
1403 ProtectHome ph;
1404
1405 r = sd_bus_message_read(message, "s", &s);
1406 if (r < 0)
1407 return r;
1408
1409 r = parse_boolean(s);
1410 if (r > 0)
1411 ph = PROTECT_HOME_YES;
1412 else if (r == 0)
1413 ph = PROTECT_HOME_NO;
1414 else {
1415 ph = protect_home_from_string(s);
1416 if (ph < 0)
1417 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value");
1418 }
1419
1420 if (mode != UNIT_CHECK) {
1421 c->protect_home = ph;
1422 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
1423 }
1424
1425 return 1;
1426
1427 } else if (streq(name, "RuntimeDirectory")) {
1428 _cleanup_strv_free_ char **l = NULL;
1429 char **p;
1430
1431 r = sd_bus_message_read_strv(message, &l);
1432 if (r < 0)
1433 return r;
1434
1435 STRV_FOREACH(p, l) {
1436 if (!filename_is_valid(*p))
1437 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Runtime directory is not valid %s", *p);
1438 }
1439
1440 if (mode != UNIT_CHECK) {
1441 _cleanup_free_ char *joined = NULL;
1442
1443 if (strv_isempty(l)) {
1444 c->runtime_directory = strv_free(c->runtime_directory);
1445 unit_write_drop_in_private_format(u, mode, name, "%s=\n", name);
1446 } else {
1447 r = strv_extend_strv(&c->runtime_directory, l, true);
1448
1449 if (r < 0)
1450 return -ENOMEM;
1451
1452 joined = strv_join_quoted(c->runtime_directory);
1453 if (!joined)
1454 return -ENOMEM;
1455
1456 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, joined);
1457 }
1458 }
1459
1460 return 1;
1461
1462 } else if (rlimit_from_string(name) >= 0) {
1463 uint64_t rl;
1464 rlim_t x;
1465
1466 r = sd_bus_message_read(message, "t", &rl);
1467 if (r < 0)
1468 return r;
1469
1470 if (rl == (uint64_t) -1)
1471 x = RLIM_INFINITY;
1472 else {
1473 x = (rlim_t) rl;
1474
1475 if ((uint64_t) x != rl)
1476 return -ERANGE;
1477 }
1478
1479 if (mode != UNIT_CHECK) {
1480 int z;
1481
1482 z = rlimit_from_string(name);
1483
1484 if (!c->rlimit[z]) {
1485 c->rlimit[z] = new(struct rlimit, 1);
1486 if (!c->rlimit[z])
1487 return -ENOMEM;
1488 }
1489
1490 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
1491
1492 if (x == RLIM_INFINITY)
1493 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
1494 else
1495 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
1496 }
1497
1498 return 1;
1499 }
1500
1501 return 0;
1502 }