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