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