]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
core: print the right string when we fail to replace specifiers in config_parse_environ()
[thirdparty/systemd.git] / src / core / dbus-execute.c
CommitLineData
4139c1b2
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
4139c1b2
LP
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 14 Lesser General Public License for more details.
4139c1b2 15
5430f7f2 16 You should have received a copy of the GNU Lesser General Public License
4139c1b2
LP
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
82c121a4 20#include <sys/prctl.h>
4139c1b2 21
57183d11
LP
22#ifdef HAVE_SECCOMP
23#include <seccomp.h>
24#endif
25
3ffd4af2 26#include "af-list.h"
b5efdb8a 27#include "alloc-util.h"
718db961 28#include "bus-util.h"
430f0182 29#include "capability-util.h"
cffaed83 30#include "cap-list.h"
3ffd4af2 31#include "dbus-execute.h"
c7040b5d 32#include "env-util.h"
cffaed83 33#include "errno-list.h"
3ffd4af2
LP
34#include "execute.h"
35#include "fd-util.h"
36#include "fileio.h"
37#include "ioprio.h"
38#include "missing.h"
83555251 39#include "mount-util.h"
417116f2 40#include "namespace.h"
6bedfcbb 41#include "parse-util.h"
9b15b784 42#include "path-util.h"
7b3e062c 43#include "process-util.h"
78f22b97 44#include "rlimit-util.h"
57183d11
LP
45#ifdef HAVE_SECCOMP
46#include "seccomp-util.h"
47#endif
cffaed83 48#include "securebits-util.h"
6bedfcbb 49#include "strv.h"
7ccbd1ae 50#include "syslog-util.h"
f900f582 51#include "unit-printf.h"
6f3e7985 52#include "user-util.h"
6bedfcbb 53#include "utf8.h"
57183d11 54
718db961 55BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
82c121a4 56
718db961 57static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
8c7be95e 58
023a4f67
LP
59static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
60
53f47dfc
YW
61static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
62
1b8689f9
LP
63static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
64static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
417116f2 65
718db961
LP
66static int property_get_environment_files(
67 sd_bus *bus,
68 const char *path,
69 const char *interface,
70 const char *property,
71 sd_bus_message *reply,
ebcf1f97
LP
72 void *userdata,
73 sd_bus_error *error) {
8c7be95e 74
718db961
LP
75 ExecContext *c = userdata;
76 char **j;
77 int r;
8c7be95e 78
718db961
LP
79 assert(bus);
80 assert(reply);
81 assert(c);
82
83 r = sd_bus_message_open_container(reply, 'a', "(sb)");
84 if (r < 0)
85 return r;
8c7be95e 86
718db961
LP
87 STRV_FOREACH(j, c->environment_files) {
88 const char *fn = *j;
8c7be95e 89
718db961
LP
90 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
91 if (r < 0)
92 return r;
8c7be95e
LP
93 }
94
718db961
LP
95 return sd_bus_message_close_container(reply);
96}
97
718db961
LP
98static int property_get_oom_score_adjust(
99 sd_bus *bus,
100 const char *path,
101 const char *interface,
102 const char *property,
103 sd_bus_message *reply,
ebcf1f97
LP
104 void *userdata,
105 sd_bus_error *error) {
718db961
LP
106
107
108 ExecContext *c = userdata;
82c121a4
LP
109 int32_t n;
110
718db961
LP
111 assert(bus);
112 assert(reply);
82c121a4
LP
113 assert(c);
114
dd6c17b1
LP
115 if (c->oom_score_adjust_set)
116 n = c->oom_score_adjust;
82c121a4 117 else {
68eda4bd 118 _cleanup_free_ char *t = NULL;
82c121a4
LP
119
120 n = 0;
718db961 121 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
e4e73a63 122 safe_atoi32(t, &n);
82c121a4
LP
123 }
124
718db961 125 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
126}
127
718db961
LP
128static int property_get_nice(
129 sd_bus *bus,
130 const char *path,
131 const char *interface,
132 const char *property,
133 sd_bus_message *reply,
ebcf1f97
LP
134 void *userdata,
135 sd_bus_error *error) {
718db961
LP
136
137
138 ExecContext *c = userdata;
82c121a4
LP
139 int32_t n;
140
718db961
LP
141 assert(bus);
142 assert(reply);
82c121a4
LP
143 assert(c);
144
145 if (c->nice_set)
146 n = c->nice;
718db961
LP
147 else {
148 errno = 0;
82c121a4 149 n = getpriority(PRIO_PROCESS, 0);
b3267152 150 if (errno > 0)
718db961
LP
151 n = 0;
152 }
82c121a4 153
718db961 154 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
155}
156
718db961
LP
157static int property_get_ioprio(
158 sd_bus *bus,
159 const char *path,
160 const char *interface,
161 const char *property,
162 sd_bus_message *reply,
ebcf1f97
LP
163 void *userdata,
164 sd_bus_error *error) {
718db961
LP
165
166
167 ExecContext *c = userdata;
82c121a4 168
718db961
LP
169 assert(bus);
170 assert(reply);
82c121a4
LP
171 assert(c);
172
7f452159
LP
173 return sd_bus_message_append(reply, "i", exec_context_get_effective_ioprio(c));
174}
82c121a4 175
7f452159
LP
176static int property_get_ioprio_class(
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
186 ExecContext *c = userdata;
187
188 assert(bus);
189 assert(reply);
190 assert(c);
191
192 return sd_bus_message_append(reply, "i", IOPRIO_PRIO_CLASS(exec_context_get_effective_ioprio(c)));
193}
194
7f452159
LP
195static int property_get_ioprio_priority(
196 sd_bus *bus,
197 const char *path,
198 const char *interface,
199 const char *property,
200 sd_bus_message *reply,
201 void *userdata,
202 sd_bus_error *error) {
203
204
205 ExecContext *c = userdata;
206
207 assert(bus);
208 assert(reply);
209 assert(c);
210
211 return sd_bus_message_append(reply, "i", IOPRIO_PRIO_DATA(exec_context_get_effective_ioprio(c)));
82c121a4
LP
212}
213
718db961
LP
214static int property_get_cpu_sched_policy(
215 sd_bus *bus,
216 const char *path,
217 const char *interface,
218 const char *property,
219 sd_bus_message *reply,
ebcf1f97
LP
220 void *userdata,
221 sd_bus_error *error) {
718db961
LP
222
223 ExecContext *c = userdata;
82c121a4
LP
224 int32_t n;
225
718db961
LP
226 assert(bus);
227 assert(reply);
82c121a4
LP
228 assert(c);
229
230 if (c->cpu_sched_set)
231 n = c->cpu_sched_policy;
718db961 232 else {
82c121a4 233 n = sched_getscheduler(0);
718db961
LP
234 if (n < 0)
235 n = SCHED_OTHER;
236 }
82c121a4 237
718db961 238 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
239}
240
718db961
LP
241static int property_get_cpu_sched_priority(
242 sd_bus *bus,
243 const char *path,
244 const char *interface,
245 const char *property,
246 sd_bus_message *reply,
ebcf1f97
LP
247 void *userdata,
248 sd_bus_error *error) {
718db961
LP
249
250 ExecContext *c = userdata;
82c121a4
LP
251 int32_t n;
252
718db961
LP
253 assert(bus);
254 assert(reply);
82c121a4
LP
255 assert(c);
256
257 if (c->cpu_sched_set)
258 n = c->cpu_sched_priority;
259 else {
b92bea5d 260 struct sched_param p = {};
82c121a4 261
82c121a4
LP
262 if (sched_getparam(0, &p) >= 0)
263 n = p.sched_priority;
e62d8c39
ZJS
264 else
265 n = 0;
82c121a4
LP
266 }
267
718db961 268 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
269}
270
718db961
LP
271static int property_get_cpu_affinity(
272 sd_bus *bus,
273 const char *path,
274 const char *interface,
275 const char *property,
276 sd_bus_message *reply,
ebcf1f97
LP
277 void *userdata,
278 sd_bus_error *error) {
82c121a4 279
718db961 280 ExecContext *c = userdata;
82c121a4 281
718db961
LP
282 assert(bus);
283 assert(reply);
284 assert(c);
82c121a4
LP
285
286 if (c->cpuset)
718db961 287 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
82c121a4 288 else
718db961 289 return sd_bus_message_append_array(reply, 'y', NULL, 0);
82c121a4
LP
290}
291
718db961
LP
292static int property_get_timer_slack_nsec(
293 sd_bus *bus,
294 const char *path,
295 const char *interface,
296 const char *property,
297 sd_bus_message *reply,
ebcf1f97
LP
298 void *userdata,
299 sd_bus_error *error) {
718db961
LP
300
301 ExecContext *c = userdata;
82c121a4
LP
302 uint64_t u;
303
718db961
LP
304 assert(bus);
305 assert(reply);
82c121a4
LP
306 assert(c);
307
3a43da28 308 if (c->timer_slack_nsec != NSEC_INFINITY)
03fae018 309 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
310 else
311 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
312
718db961 313 return sd_bus_message_append(reply, "t", u);
82c121a4
LP
314}
315
718db961
LP
316static int property_get_capability_bounding_set(
317 sd_bus *bus,
318 const char *path,
319 const char *interface,
320 const char *property,
321 sd_bus_message *reply,
ebcf1f97
LP
322 void *userdata,
323 sd_bus_error *error) {
260abb78 324
718db961
LP
325 ExecContext *c = userdata;
326
327 assert(bus);
328 assert(reply);
260abb78
LP
329 assert(c);
330
a103496c 331 return sd_bus_message_append(reply, "t", c->capability_bounding_set);
260abb78
LP
332}
333
755d4b67
IP
334static int property_get_ambient_capabilities(
335 sd_bus *bus,
336 const char *path,
337 const char *interface,
338 const char *property,
339 sd_bus_message *reply,
340 void *userdata,
341 sd_bus_error *error) {
342
343 ExecContext *c = userdata;
344
345 assert(bus);
346 assert(reply);
347 assert(c);
348
349 return sd_bus_message_append(reply, "t", c->capability_ambient_set);
350}
351
479050b3 352static int property_get_empty_string(
718db961
LP
353 sd_bus *bus,
354 const char *path,
355 const char *interface,
356 const char *property,
357 sd_bus_message *reply,
ebcf1f97
LP
358 void *userdata,
359 sd_bus_error *error) {
718db961 360
718db961
LP
361 assert(bus);
362 assert(reply);
82c121a4 363
479050b3 364 return sd_bus_message_append(reply, "s", "");
82c121a4
LP
365}
366
718db961
LP
367static int property_get_syscall_filter(
368 sd_bus *bus,
369 const char *path,
370 const char *interface,
371 const char *property,
372 sd_bus_message *reply,
ebcf1f97
LP
373 void *userdata,
374 sd_bus_error *error) {
82c121a4 375
17df7223
LP
376 ExecContext *c = userdata;
377 _cleanup_strv_free_ char **l = NULL;
57183d11
LP
378 int r;
379
351a19b1 380#ifdef HAVE_SECCOMP
17df7223
LP
381 Iterator i;
382 void *id;
351a19b1 383#endif
17df7223
LP
384
385 assert(bus);
386 assert(reply);
387 assert(c);
388
57183d11
LP
389 r = sd_bus_message_open_container(reply, 'r', "bas");
390 if (r < 0)
391 return r;
392
393 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
394 if (r < 0)
395 return r;
396
351a19b1 397#ifdef HAVE_SECCOMP
17df7223
LP
398 SET_FOREACH(id, c->syscall_filter, i) {
399 char *name;
400
401 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
402 if (!name)
403 continue;
404
6e18964d
ZJS
405 r = strv_consume(&l, name);
406 if (r < 0)
407 return r;
17df7223 408 }
351a19b1 409#endif
17df7223
LP
410
411 strv_sort(l);
412
57183d11
LP
413 r = sd_bus_message_append_strv(reply, l);
414 if (r < 0)
415 return r;
17df7223 416
57183d11
LP
417 return sd_bus_message_close_container(reply);
418}
17df7223 419
57183d11
LP
420static int property_get_syscall_archs(
421 sd_bus *bus,
422 const char *path,
423 const char *interface,
424 const char *property,
425 sd_bus_message *reply,
426 void *userdata,
427 sd_bus_error *error) {
428
429 ExecContext *c = userdata;
430 _cleanup_strv_free_ char **l = NULL;
431 int r;
432
433#ifdef HAVE_SECCOMP
434 Iterator i;
435 void *id;
436#endif
437
438 assert(bus);
439 assert(reply);
440 assert(c);
17df7223 441
57183d11
LP
442#ifdef HAVE_SECCOMP
443 SET_FOREACH(id, c->syscall_archs, i) {
444 const char *name;
445
446 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
447 if (!name)
448 continue;
449
450 r = strv_extend(&l, name);
451 if (r < 0)
452 return -ENOMEM;
17df7223 453 }
57183d11
LP
454#endif
455
456 strv_sort(l);
457
458 r = sd_bus_message_append_strv(reply, l);
459 if (r < 0)
460 return r;
17df7223 461
57183d11 462 return 0;
17df7223
LP
463}
464
465static int property_get_syscall_errno(
466 sd_bus *bus,
467 const char *path,
468 const char *interface,
469 const char *property,
470 sd_bus_message *reply,
471 void *userdata,
472 sd_bus_error *error) {
473
718db961 474 ExecContext *c = userdata;
82c121a4 475
718db961
LP
476 assert(bus);
477 assert(reply);
478 assert(c);
82c121a4 479
17df7223 480 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
718db961 481}
82c121a4 482
5f8640fb
LP
483static int property_get_selinux_context(
484 sd_bus *bus,
485 const char *path,
486 const char *interface,
487 const char *property,
488 sd_bus_message *reply,
489 void *userdata,
490 sd_bus_error *error) {
491
492 ExecContext *c = userdata;
493
494 assert(bus);
495 assert(reply);
496 assert(c);
497
498 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
499}
500
eef65bf3
MS
501static int property_get_apparmor_profile(
502 sd_bus *bus,
503 const char *path,
504 const char *interface,
505 const char *property,
506 sd_bus_message *reply,
507 void *userdata,
508 sd_bus_error *error) {
509
510 ExecContext *c = userdata;
511
512 assert(bus);
513 assert(reply);
514 assert(c);
515
516 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
517}
518
2ca620c4
WC
519static int property_get_smack_process_label(
520 sd_bus *bus,
521 const char *path,
522 const char *interface,
523 const char *property,
524 sd_bus_message *reply,
525 void *userdata,
526 sd_bus_error *error) {
527
528 ExecContext *c = userdata;
529
530 assert(bus);
531 assert(reply);
532 assert(c);
533
534 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
535}
536
ac45f971
LP
537static int property_get_personality(
538 sd_bus *bus,
539 const char *path,
540 const char *interface,
541 const char *property,
542 sd_bus_message *reply,
543 void *userdata,
544 sd_bus_error *error) {
545
546 ExecContext *c = userdata;
547
548 assert(bus);
549 assert(reply);
550 assert(c);
551
552 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
553}
554
4298d0b5
LP
555static int property_get_address_families(
556 sd_bus *bus,
557 const char *path,
558 const char *interface,
559 const char *property,
560 sd_bus_message *reply,
561 void *userdata,
562 sd_bus_error *error) {
563
564 ExecContext *c = userdata;
565 _cleanup_strv_free_ char **l = NULL;
566 Iterator i;
567 void *af;
568 int r;
569
570 assert(bus);
571 assert(reply);
572 assert(c);
573
574 r = sd_bus_message_open_container(reply, 'r', "bas");
575 if (r < 0)
576 return r;
577
578 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
579 if (r < 0)
580 return r;
581
582 SET_FOREACH(af, c->address_families, i) {
583 const char *name;
584
585 name = af_to_name(PTR_TO_INT(af));
586 if (!name)
587 continue;
588
589 r = strv_extend(&l, name);
590 if (r < 0)
591 return -ENOMEM;
592 }
593
594 strv_sort(l);
595
596 r = sd_bus_message_append_strv(reply, l);
597 if (r < 0)
598 return r;
599
600 return sd_bus_message_close_container(reply);
601}
602
5f5d8eab
LP
603static int property_get_working_directory(
604 sd_bus *bus,
605 const char *path,
606 const char *interface,
607 const char *property,
608 sd_bus_message *reply,
609 void *userdata,
610 sd_bus_error *error) {
611
612 ExecContext *c = userdata;
613 const char *wd;
614
615 assert(bus);
616 assert(reply);
617 assert(c);
618
619 if (c->working_directory_home)
620 wd = "~";
621 else
622 wd = c->working_directory;
623
624 if (c->working_directory_missing_ok)
625 wd = strjoina("!", wd);
626
627 return sd_bus_message_append(reply, "s", wd);
628}
629
06f2ccf9
EV
630static int property_get_syslog_level(
631 sd_bus *bus,
632 const char *path,
633 const char *interface,
634 const char *property,
635 sd_bus_message *reply,
636 void *userdata,
637 sd_bus_error *error) {
638
639 ExecContext *c = userdata;
640
641 assert(bus);
642 assert(reply);
643 assert(c);
644
645 return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
646}
647
648static int property_get_syslog_facility(
649 sd_bus *bus,
650 const char *path,
651 const char *interface,
652 const char *property,
653 sd_bus_message *reply,
654 void *userdata,
655 sd_bus_error *error) {
656
657 ExecContext *c = userdata;
658
659 assert(bus);
660 assert(reply);
661 assert(c);
662
663 return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
664}
665
52c239d7
LB
666static int property_get_input_fdname(
667 sd_bus *bus,
668 const char *path,
669 const char *interface,
670 const char *property,
671 sd_bus_message *reply,
672 void *userdata,
673 sd_bus_error *error) {
674
675 ExecContext *c = userdata;
676 const char *name;
677
678 assert(bus);
679 assert(c);
680 assert(property);
681 assert(reply);
682
683 name = exec_context_fdname(c, STDIN_FILENO);
684
685 return sd_bus_message_append(reply, "s", name);
686}
687
688static int property_get_output_fdname(
689 sd_bus *bus,
690 const char *path,
691 const char *interface,
692 const char *property,
693 sd_bus_message *reply,
694 void *userdata,
695 sd_bus_error *error) {
696
697 ExecContext *c = userdata;
698 const char *name = NULL;
699
700 assert(bus);
701 assert(c);
702 assert(property);
703 assert(reply);
704
705 if (c->std_output == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardOutputFileDescriptorName"))
706 name = exec_context_fdname(c, STDOUT_FILENO);
707 else if (c->std_error == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardErrorFileDescriptorName"))
708 name = exec_context_fdname(c, STDERR_FILENO);
709
710 return sd_bus_message_append(reply, "s", name);
711}
712
d2d6c096
LP
713static int property_get_bind_paths(
714 sd_bus *bus,
715 const char *path,
716 const char *interface,
717 const char *property,
718 sd_bus_message *reply,
719 void *userdata,
720 sd_bus_error *error) {
721
722 ExecContext *c = userdata;
723 unsigned i;
724 bool ro;
725 int r;
726
727 assert(bus);
728 assert(c);
729 assert(property);
730 assert(reply);
731
732 ro = !!strstr(property, "ReadOnly");
733
734 r = sd_bus_message_open_container(reply, 'a', "(ssbt)");
735 if (r < 0)
736 return r;
737
738 for (i = 0; i < c->n_bind_mounts; i++) {
739
740 if (ro != c->bind_mounts[i].read_only)
741 continue;
742
743 r = sd_bus_message_append(
744 reply, "(ssbt)",
745 c->bind_mounts[i].source,
746 c->bind_mounts[i].destination,
747 c->bind_mounts[i].ignore_enoent,
c9b06108 748 c->bind_mounts[i].recursive ? (uint64_t) MS_REC : (uint64_t) 0);
d2d6c096
LP
749 if (r < 0)
750 return r;
751 }
752
753 return sd_bus_message_close_container(reply);
754}
755
718db961
LP
756const sd_bus_vtable bus_exec_vtable[] = {
757 SD_BUS_VTABLE_START(0),
556089dc
LP
758 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
759 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
b4c14404 760 SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
00819cc1 761 SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL, offsetof(ExecContext, unset_environment), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 762 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 763 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 764 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 765 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 766 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 767 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 768 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 769 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 770 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 771 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 772 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 773 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 774 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 775 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 776 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 777 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 778 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 779 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 780 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 781 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 782 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 783 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 784 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 785 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 786 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 787 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 788 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 789 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 790 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 791 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 792 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 793 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 794 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
5f5d8eab 795 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 796 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
915e6d16 797 SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
798 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
799 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
7f452159
LP
800 SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST),
801 SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
802 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
803 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
804 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
805 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
806 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
807 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
808 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
52c239d7 809 SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_input_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 810 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
52c239d7 811 SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 812 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
52c239d7 813 SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
814 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
815 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
816 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
817 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
818 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
819 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
820 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
06f2ccf9
EV
821 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
822 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
823 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
824 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
755d4b67 825 SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
826 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
827 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
29206d46 828 SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
00d9ef85 829 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 830 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 831 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
2a624c36
AP
832 SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST),
833 SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST),
834 SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
835 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
836 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
7f112f50 837 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
59eeb84b 838 SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST),
502d704e 839 SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_modules), SD_BUS_VTABLE_PROPERTY_CONST),
59eeb84b 840 SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST),
d251207d
LP
841 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
842 SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
1b8689f9
LP
843 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
844 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
845 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
846 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
023a4f67 847 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
5f8640fb 848 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
eef65bf3 849 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2ca620c4 850 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
851 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
852 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
57183d11
LP
853 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
854 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
17df7223 855 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
ac45f971 856 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
78e864e5 857 SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
4298d0b5 858 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
53f47dfc 859 SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
3536f49e
YW
860 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].mode), SD_BUS_VTABLE_PROPERTY_CONST),
861 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].paths), SD_BUS_VTABLE_PROPERTY_CONST),
e940c1ef
YW
862 SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
863 SD_BUS_PROPERTY("StateDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
3536f49e
YW
864 SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
865 SD_BUS_PROPERTY("CacheDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
866 SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST),
867 SD_BUS_PROPERTY("LogsDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].paths), SD_BUS_VTABLE_PROPERTY_CONST),
868 SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST),
869 SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST),
f3e43635 870 SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
f4170c67 871 SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
6a8c2d59 872 SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
d2d6c096
LP
873 SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
874 SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
5d997827 875 SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST),
7f452159
LP
876
877 /* Obsolete/redundant properties: */
878 SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
879 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
880 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
881 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
882 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
883
718db961
LP
884 SD_BUS_VTABLE_END
885};
82c121a4 886
4d4c80d0
LP
887static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
888 int r;
889
890 assert(reply);
891 assert(c);
892
893 if (!c->path)
894 return 0;
895
896 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
897 if (r < 0)
898 return r;
899
900 r = sd_bus_message_append(reply, "s", c->path);
901 if (r < 0)
902 return r;
903
904 r = sd_bus_message_append_strv(reply, c->argv);
905 if (r < 0)
906 return r;
907
908 r = sd_bus_message_append(reply, "bttttuii",
3ed0cd26 909 !!(c->flags & EXEC_COMMAND_IGNORE_FAILURE),
4d4c80d0
LP
910 c->exec_status.start_timestamp.realtime,
911 c->exec_status.start_timestamp.monotonic,
912 c->exec_status.exit_timestamp.realtime,
913 c->exec_status.exit_timestamp.monotonic,
914 (uint32_t) c->exec_status.pid,
915 (int32_t) c->exec_status.code,
916 (int32_t) c->exec_status.status);
917 if (r < 0)
918 return r;
919
920 return sd_bus_message_close_container(reply);
921}
922
718db961
LP
923int bus_property_get_exec_command(
924 sd_bus *bus,
925 const char *path,
926 const char *interface,
927 const char *property,
928 sd_bus_message *reply,
ebcf1f97
LP
929 void *userdata,
930 sd_bus_error *ret_error) {
fe68089d 931
4d4c80d0 932 ExecCommand *c = (ExecCommand*) userdata;
718db961 933 int r;
fe68089d 934
718db961
LP
935 assert(bus);
936 assert(reply);
fe68089d 937
718db961
LP
938 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
939 if (r < 0)
940 return r;
fe68089d 941
4d4c80d0
LP
942 r = append_exec_command(reply, c);
943 if (r < 0)
944 return r;
fe68089d 945
4d4c80d0
LP
946 return sd_bus_message_close_container(reply);
947}
718db961 948
4d4c80d0
LP
949int bus_property_get_exec_command_list(
950 sd_bus *bus,
951 const char *path,
952 const char *interface,
953 const char *property,
954 sd_bus_message *reply,
955 void *userdata,
956 sd_bus_error *ret_error) {
718db961 957
4d4c80d0
LP
958 ExecCommand *c = *(ExecCommand**) userdata;
959 int r;
718db961 960
4d4c80d0
LP
961 assert(bus);
962 assert(reply);
963
964 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
965 if (r < 0)
966 return r;
718db961 967
4d4c80d0
LP
968 LIST_FOREACH(command, c, c) {
969 r = append_exec_command(reply, c);
718db961
LP
970 if (r < 0)
971 return r;
fe68089d
LP
972 }
973
718db961 974 return sd_bus_message_close_container(reply);
8351ceae 975}
c7040b5d
LP
976
977int bus_exec_context_set_transient_property(
978 Unit *u,
979 ExecContext *c,
980 const char *name,
981 sd_bus_message *message,
982 UnitSetPropertiesMode mode,
983 sd_bus_error *error) {
984
cab2aca3
LP
985 const char *soft = NULL;
986 int r, ri;
c7040b5d
LP
987
988 assert(u);
989 assert(c);
990 assert(name);
991 assert(message);
992
993 if (streq(name, "User")) {
994 const char *uu;
995
996 r = sd_bus_message_read(message, "s", &uu);
997 if (r < 0)
998 return r;
999
6f3e7985
LP
1000 if (!isempty(uu) && !valid_user_group_name_or_id(uu))
1001 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user name: %s", uu);
1002
c7040b5d 1003 if (mode != UNIT_CHECK) {
76736280
LP
1004
1005 if (isempty(uu))
1006 c->user = mfree(c->user);
1007 else if (free_and_strdup(&c->user, uu) < 0)
1008 return -ENOMEM;
c7040b5d 1009
b27b4b51 1010 unit_write_drop_in_private_format(u, mode, name, "User=%s", uu);
c7040b5d
LP
1011 }
1012
1013 return 1;
1014
1015 } else if (streq(name, "Group")) {
1016 const char *gg;
1017
1018 r = sd_bus_message_read(message, "s", &gg);
1019 if (r < 0)
1020 return r;
1021
6f3e7985
LP
1022 if (!isempty(gg) && !valid_user_group_name_or_id(gg))
1023 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group name: %s", gg);
1024
c7040b5d 1025 if (mode != UNIT_CHECK) {
76736280
LP
1026
1027 if (isempty(gg))
1028 c->group = mfree(c->group);
1029 else if (free_and_strdup(&c->group, gg) < 0)
1030 return -ENOMEM;
c7040b5d 1031
b27b4b51 1032 unit_write_drop_in_private_format(u, mode, name, "Group=%s", gg);
c7040b5d
LP
1033 }
1034
1035 return 1;
cffaed83
YW
1036
1037 } else if (streq(name, "SupplementaryGroups")) {
1038 _cleanup_strv_free_ char **l = NULL;
1039 char **p;
1040
1041 r = sd_bus_message_read_strv(message, &l);
1042 if (r < 0)
1043 return r;
1044
1045 STRV_FOREACH(p, l) {
1046 if (!isempty(*p) && !valid_user_group_name_or_id(*p))
1047 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid supplementary group names");
1048 }
1049
1050 if (mode != UNIT_CHECK) {
1051 if (strv_length(l) == 0) {
1052 c->supplementary_groups = strv_free(c->supplementary_groups);
1053 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
1054 } else {
1055 _cleanup_free_ char *joined = NULL;
1056
1057 r = strv_extend_strv(&c->supplementary_groups, l, true);
1058 if (r < 0)
1059 return -ENOMEM;
1060
1061 joined = strv_join(c->supplementary_groups, " ");
1062 if (!joined)
1063 return -ENOMEM;
1064
1065 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
1066 }
1067 }
1068
1069 return 1;
1070
de53c417
EV
1071 } else if (streq(name, "SyslogIdentifier")) {
1072 const char *id;
c7040b5d 1073
de53c417
EV
1074 r = sd_bus_message_read(message, "s", &id);
1075 if (r < 0)
1076 return r;
1077
1078 if (mode != UNIT_CHECK) {
76736280
LP
1079
1080 if (isempty(id))
1081 c->syslog_identifier = mfree(c->syslog_identifier);
1082 else if (free_and_strdup(&c->syslog_identifier, id) < 0)
1083 return -ENOMEM;
de53c417 1084
b27b4b51 1085 unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s", id);
de53c417
EV
1086 }
1087
a8a13575
EV
1088 return 1;
1089 } else if (streq(name, "SyslogLevel")) {
8d1dd6ab 1090 int32_t level;
a8a13575
EV
1091
1092 r = sd_bus_message_read(message, "i", &level);
1093 if (r < 0)
1094 return r;
1095
e0d6e0fa
EV
1096 if (!log_level_is_valid(level))
1097 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
1098
a8a13575
EV
1099 if (mode != UNIT_CHECK) {
1100 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
b27b4b51 1101 unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i", level);
a8a13575
EV
1102 }
1103
460ed929
EV
1104 return 1;
1105 } else if (streq(name, "SyslogFacility")) {
8d1dd6ab 1106 int32_t facility;
460ed929
EV
1107
1108 r = sd_bus_message_read(message, "i", &facility);
1109 if (r < 0)
1110 return r;
1111
e0d6e0fa
EV
1112 if (!log_facility_unshifted_is_valid(facility))
1113 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
1114
460ed929
EV
1115 if (mode != UNIT_CHECK) {
1116 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
b27b4b51 1117 unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i", facility);
460ed929
EV
1118 }
1119
cffaed83
YW
1120 return 1;
1121 } else if (streq(name, "SecureBits")) {
1122 int n;
1123
1124 r = sd_bus_message_read(message, "i", &n);
1125 if (r < 0)
1126 return r;
1127
1128 if (!secure_bits_is_valid(n))
1129 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid secure bits");
1130
1131 if (mode != UNIT_CHECK) {
1132 _cleanup_free_ char *str = NULL;
1133
1134 c->secure_bits = n;
1135 r = secure_bits_to_string_alloc(n, &str);
1136 if (r < 0)
1137 return r;
1138
1139 unit_write_drop_in_private_format(u, mode, name, "SecureBits=%s", str);
1140 }
1141
1142 return 1;
1143 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
1144 uint64_t n;
1145
1146 r = sd_bus_message_read(message, "t", &n);
1147 if (r < 0)
1148 return r;
1149
1150 if (mode != UNIT_CHECK) {
1151 _cleanup_free_ char *str = NULL;
1152
1153 if (streq(name, "CapabilityBoundingSet"))
1154 c->capability_bounding_set = n;
1155 else /* "AmbientCapabilities" */
1156 c->capability_ambient_set = n;
1157
1158 r = capability_set_to_string_alloc(n, &str);
1159 if (r < 0)
1160 return r;
1161
1162 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
1163 }
1164
1165 return 1;
1166
1167 } else if (streq(name, "Personality")) {
1168 const char *s;
1169 unsigned long p;
1170
1171 r = sd_bus_message_read(message, "s", &s);
1172 if (r < 0)
1173 return r;
1174
1175 p = personality_from_string(s);
1176 if (p == PERSONALITY_INVALID)
1177 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid personality");
1178
1179 if (mode != UNIT_CHECK) {
1180 _cleanup_free_ char *str = NULL;
1181
1182 c->personality = p;
1183 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
1184 }
1185
1186 return 1;
1187
1188#ifdef HAVE_SECCOMP
1189
1190 } else if (streq(name, "SystemCallFilter")) {
1191 int whitelist;
1192 _cleanup_strv_free_ char **l;
1193
1194 r = sd_bus_message_enter_container(message, 'r', "bas");
1195 if (r < 0)
1196 return r;
1197
1198 r = sd_bus_message_read(message, "b", &whitelist);
1199 if (r < 0)
1200 return r;
1201
1202 r = sd_bus_message_read_strv(message, &l);
1203 if (r < 0)
1204 return r;
1205
1206 r = sd_bus_message_exit_container(message);
1207 if (r < 0)
1208 return r;
1209
1210 if (mode != UNIT_CHECK) {
1211 _cleanup_free_ char *joined = NULL;
1212
1213 if (strv_length(l) == 0) {
1214 c->syscall_whitelist = false;
1215 c->syscall_filter = set_free(c->syscall_filter);
1216 } else {
1217 char **s;
1218
1219 c->syscall_whitelist = whitelist;
1220
1221 r = set_ensure_allocated(&c->syscall_filter, NULL);
1222 if (r < 0)
1223 return r;
1224
1225 STRV_FOREACH(s, l) {
1226 if (**s == '@') {
1227 const SyscallFilterSet *set;
1228 const char *i;
1229
1230 set = syscall_filter_set_find(*s);
1231 if (!set)
1232 return -EINVAL;
1233
1234 NULSTR_FOREACH(i, set->value) {
1235 int id;
1236
1237 id = seccomp_syscall_resolve_name(i);
1238 if (id == __NR_SCMP_ERROR)
1239 return -EINVAL;
1240
1241 r = set_put(c->address_families, INT_TO_PTR(id + 1));
1242 if (r < 0)
1243 return r;
1244 }
1245
1246 } else {
1247 int id;
1248
1249 id = seccomp_syscall_resolve_name(*s);
1250 if (id == __NR_SCMP_ERROR)
1251 return -EINVAL;
1252
1253 r = set_put(c->address_families, INT_TO_PTR(id + 1));
1254 if (r < 0)
1255 return r;
1256 }
1257 }
1258 }
1259
1260 joined = strv_join(l, " ");
1261 if (!joined)
1262 return -ENOMEM;
1263
1264 unit_write_drop_in_private_format(u, mode, name, "SystemCallFilter=%s%s", whitelist ? "" : "~", joined);
1265 }
1266
1267 return 1;
1268
1269 } else if (streq(name, "SystemCallArchitectures")) {
1270 _cleanup_strv_free_ char **l = NULL;
1271
1272 r = sd_bus_message_read_strv(message, &l);
1273 if (r < 0)
1274 return r;
1275
1276 if (mode != UNIT_CHECK) {
1277 _cleanup_free_ char *joined = NULL;
1278
1279 if (strv_length(l) == 0)
1280 c->syscall_archs = set_free(c->syscall_archs);
1281 else {
1282 char **s;
1283
1284 r = set_ensure_allocated(&c->syscall_archs, NULL);
1285 if (r < 0)
1286 return r;
1287
1288 STRV_FOREACH(s, l) {
1289 uint32_t a;
1290
1291 r = seccomp_arch_from_string(*s, &a);
1292 if (r < 0)
1293 return r;
1294
1295 r = set_put(c->syscall_archs, UINT32_TO_PTR(a + 1));
1296 if (r < 0)
1297 return r;
1298 }
1299
1300 }
1301
1302 joined = strv_join(l, " ");
1303 if (!joined)
1304 return -ENOMEM;
1305
1306 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
1307 }
1308
1309 return 1;
1310
1311 } else if (streq(name, "SystemCallErrorNumber")) {
1312 int32_t n;
1313 const char *str;
1314
1315 r = sd_bus_message_read(message, "i", &n);
1316 if (r < 0)
1317 return r;
1318
1319 str = errno_to_name(n);
1320 if (!str)
1321 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SystemCallErrorNumber");
1322
1323 if (mode != UNIT_CHECK) {
1324 c->syscall_errno = n;
1325
1326 unit_write_drop_in_private_format(u, mode, name, "SystemCallErrorNumber=%s", str);
1327 }
1328
1329 return 1;
1330
1331 } else if (streq(name, "RestrictAddressFamilies")) {
1332 int whitelist;
1333 _cleanup_strv_free_ char **l;
1334
1335 r = sd_bus_message_enter_container(message, 'r', "bas");
1336 if (r < 0)
1337 return r;
1338
1339 r = sd_bus_message_read(message, "b", &whitelist);
1340 if (r < 0)
1341 return r;
1342
1343 r = sd_bus_message_read_strv(message, &l);
1344 if (r < 0)
1345 return r;
1346
1347 r = sd_bus_message_exit_container(message);
1348 if (r < 0)
1349 return r;
1350
1351 if (mode != UNIT_CHECK) {
1352 _cleanup_free_ char *joined = NULL;
1353
1354 if (strv_length(l) == 0) {
1355 c->address_families_whitelist = false;
1356 c->address_families = set_free(c->address_families);
1357 } else {
1358 char **s;
1359
1360 c->address_families_whitelist = whitelist;
1361
1362 r = set_ensure_allocated(&c->address_families, NULL);
1363 if (r < 0)
1364 return r;
1365
1366 STRV_FOREACH(s, l) {
1367 int af;
1368
1369 af = af_from_name(*s);
1370 if (af <= 0)
1371 return -EINVAL;
1372
1373 r = set_put(c->address_families, INT_TO_PTR(af));
1374 if (r < 0)
1375 return r;
1376 }
1377 }
1378
1379 joined = strv_join(l, " ");
1380 if (!joined)
1381 return -ENOMEM;
1382
1383 unit_write_drop_in_private_format(u, mode, name, "RestrictAddressFamilies=%s%s", whitelist ? "" : "~", joined);
1384 }
1385
1386 return 1;
1387#endif
1388
1389 } else if (streq(name, "CPUSchedulingPolicy")) {
1390 int32_t n;
1391
1392 r = sd_bus_message_read(message, "i", &n);
1393 if (r < 0)
1394 return r;
1395
1396 if (!sched_policy_is_valid(n))
1397 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy");
1398
1399 if (mode != UNIT_CHECK) {
1400 _cleanup_free_ char *str = NULL;
1401
1402 c->cpu_sched_policy = n;
1403 r = sched_policy_to_string_alloc(n, &str);
1404 if (r < 0)
1405 return r;
1406
1407 unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPolicy=%s", str);
1408 }
1409
1410 return 1;
1411
1412 } else if (streq(name, "CPUSchedulingPriority")) {
1413 int32_t n;
1414
1415 r = sd_bus_message_read(message, "i", &n);
1416 if (r < 0)
1417 return r;
1418
1419 if (!ioprio_priority_is_valid(n))
1420 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority");
1421
1422 if (mode != UNIT_CHECK) {
1423 c->cpu_sched_priority = n;
1424 unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPriority=%i", n);
1425 }
1426
1427 return 1;
1428
1429 } else if (streq(name, "CPUAffinity")) {
1430 const void *a;
1431 size_t n = 0;
1432
1433 r = sd_bus_message_read_array(message, 'y', &a, &n);
1434 if (r < 0)
1435 return r;
1436
1437 if (mode != UNIT_CHECK) {
1438 if (n == 0) {
1439 c->cpuset = mfree(c->cpuset);
1440 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
1441 } else {
1442 _cleanup_free_ char *str = NULL;
1443 uint8_t *l;
1444 size_t allocated = 0, len = 0, i;
1445
1446 c->cpuset = (cpu_set_t*) memdup(a, sizeof(cpu_set_t) * n);
1447 if (c->cpuset)
1448 return -ENOMEM;
1449
1450 l = (uint8_t*) a;
1451 for (i = 0; i < n; i++) {
1452 _cleanup_free_ char *p = NULL;
1453 size_t add;
1454
1455 r = asprintf(&p, "%hhi", l[i]);
1456 if (r < 0)
1457 return -ENOMEM;
1458
1459 add = strlen(p);
1460
1461 if (GREEDY_REALLOC(str, allocated, len + add + 2))
1462 return -ENOMEM;
1463
1464 strcpy(mempcpy(str + len, p, add), " ");
1465 len += add + 1;
1466 }
1467
1468 if (len != 0)
1469 str[len - 1] = '\0';
1470
1471 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
1472 }
1473 }
1474
de53c417 1475 return 1;
c7040b5d 1476 } else if (streq(name, "Nice")) {
8d1dd6ab 1477 int32_t n;
c7040b5d
LP
1478
1479 r = sd_bus_message_read(message, "i", &n);
1480 if (r < 0)
1481 return r;
1482
41bf0590 1483 if (!nice_is_valid(n))
c7040b5d
LP
1484 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
1485
1486 if (mode != UNIT_CHECK) {
1487 c->nice = n;
b27b4b51 1488 unit_write_drop_in_private_format(u, mode, name, "Nice=%i", n);
c7040b5d
LP
1489 }
1490
1491 return 1;
1492
7f452159
LP
1493 } else if (streq(name, "IOSchedulingClass")) {
1494 int32_t q;
1495
1496 r = sd_bus_message_read(message, "i", &q);
1497 if (r < 0)
1498 return r;
1499
1500 if (!ioprio_class_is_valid(q))
1501 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q);
1502
1503 if (mode != UNIT_CHECK) {
1504 _cleanup_free_ char *s = NULL;
1505
1506 r = ioprio_class_to_string_alloc(q, &s);
1507 if (r < 0)
1508 return r;
1509
1510 c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio));
1511 c->ioprio_set = true;
1512
1513 unit_write_drop_in_private_format(u, mode, name, "IOSchedulingClass=%s", s);
1514 }
1515
1516 return 1;
1517
1518 } else if (streq(name, "IOSchedulingPriority")) {
1519 int32_t p;
1520
1521 r = sd_bus_message_read(message, "i", &p);
1522 if (r < 0)
1523 return r;
1524
1525 if (!ioprio_priority_is_valid(p))
1526 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
1527
1528 if (mode != UNIT_CHECK) {
1529 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p);
1530 c->ioprio_set = true;
1531
1532 unit_write_drop_in_private_format(u, mode, name, "IOSchedulingPriority=%i", p);
1533 }
1534
1535 return 1;
1536
915e6d16 1537 } else if (STR_IN_SET(name, "TTYPath", "RootDirectory", "RootImage")) {
602b8355 1538 const char *s;
9b15b784 1539
602b8355 1540 r = sd_bus_message_read(message, "s", &s);
9b15b784
LP
1541 if (r < 0)
1542 return r;
1543
602b8355
NC
1544 if (!path_is_absolute(s))
1545 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
9b15b784
LP
1546
1547 if (mode != UNIT_CHECK) {
5f5d8eab
LP
1548 if (streq(name, "TTYPath"))
1549 r = free_and_strdup(&c->tty_path, s);
915e6d16
LP
1550 else if (streq(name, "RootImage"))
1551 r = free_and_strdup(&c->root_image, s);
5f5d8eab
LP
1552 else {
1553 assert(streq(name, "RootDirectory"));
1554 r = free_and_strdup(&c->root_directory, s);
602b8355 1555 }
5f5d8eab
LP
1556 if (r < 0)
1557 return r;
9b15b784 1558
b27b4b51 1559 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
9b15b784
LP
1560 }
1561
1562 return 1;
1563
5f5d8eab
LP
1564 } else if (streq(name, "WorkingDirectory")) {
1565 const char *s;
1566 bool missing_ok;
1567
1568 r = sd_bus_message_read(message, "s", &s);
1569 if (r < 0)
1570 return r;
1571
1572 if (s[0] == '-') {
1573 missing_ok = true;
1574 s++;
1575 } else
1576 missing_ok = false;
1577
1578 if (!streq(s, "~") && !path_is_absolute(s))
1579 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
1580
1581 if (mode != UNIT_CHECK) {
1582 if (streq(s, "~")) {
1583 c->working_directory = mfree(c->working_directory);
1584 c->working_directory_home = true;
1585 } else {
1586 r = free_and_strdup(&c->working_directory, s);
1587 if (r < 0)
1588 return r;
1589
1590 c->working_directory_home = false;
1591 }
1592
1593 c->working_directory_missing_ok = missing_ok;
b27b4b51 1594 unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
5f5d8eab
LP
1595 }
1596
1597 return 1;
1598
9b15b784
LP
1599 } else if (streq(name, "StandardInput")) {
1600 const char *s;
1601 ExecInput p;
1602
1603 r = sd_bus_message_read(message, "s", &s);
1604 if (r < 0)
1605 return r;
1606
1607 p = exec_input_from_string(s);
1608 if (p < 0)
1609 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
1610
1611 if (mode != UNIT_CHECK) {
1612 c->std_input = p;
1613
b27b4b51 1614 unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s", exec_input_to_string(p));
9b15b784
LP
1615 }
1616
1617 return 1;
1618
9b15b784
LP
1619 } else if (streq(name, "StandardOutput")) {
1620 const char *s;
1621 ExecOutput p;
1622
1623 r = sd_bus_message_read(message, "s", &s);
1624 if (r < 0)
1625 return r;
1626
1627 p = exec_output_from_string(s);
1628 if (p < 0)
1629 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
1630
1631 if (mode != UNIT_CHECK) {
1632 c->std_output = p;
1633
b27b4b51 1634 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s", exec_output_to_string(p));
9b15b784
LP
1635 }
1636
1637 return 1;
1638
1639 } else if (streq(name, "StandardError")) {
1640 const char *s;
1641 ExecOutput p;
1642
1643 r = sd_bus_message_read(message, "s", &s);
1644 if (r < 0)
1645 return r;
1646
1647 p = exec_output_from_string(s);
1648 if (p < 0)
1649 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
1650
1651 if (mode != UNIT_CHECK) {
1652 c->std_error = p;
1653
b27b4b51 1654 unit_write_drop_in_private_format(u, mode, name, "StandardError=%s", exec_output_to_string(p));
9b15b784
LP
1655 }
1656
1657 return 1;
1658
52c239d7
LB
1659 } else if (STR_IN_SET(name,
1660 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
1661 const char *s;
1662
1663 r = sd_bus_message_read(message, "s", &s);
1664 if (r < 0)
1665 return r;
1666
1667 if (!fdname_is_valid(s))
1668 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
1669
1670 if (mode != UNIT_CHECK) {
1671 if (streq(name, "StandardInputFileDescriptorName")) {
1672 c->std_input = EXEC_INPUT_NAMED_FD;
1673 r = free_and_strdup(&c->stdio_fdname[STDIN_FILENO], s);
1674 if (r < 0)
1675 return r;
1676 unit_write_drop_in_private_format(u, mode, name, "StandardInput=fd:%s", s);
1677 } else if (streq(name, "StandardOutputFileDescriptorName")) {
1678 c->std_output = EXEC_OUTPUT_NAMED_FD;
1679 r = free_and_strdup(&c->stdio_fdname[STDOUT_FILENO], s);
1680 if (r < 0)
1681 return r;
1682 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=fd:%s", s);
1683 } else if (streq(name, "StandardErrorFileDescriptorName")) {
1684 c->std_error = EXEC_OUTPUT_NAMED_FD;
1685 r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], s);
1686 if (r < 0)
1687 return r;
1688 unit_write_drop_in_private_format(u, mode, name, "StandardError=fd:%s", s);
1689 }
1690 }
1691
1692 return 1;
1693
b9c50073 1694 } else if (STR_IN_SET(name,
cffaed83 1695 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate",
d251207d 1696 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers",
29206d46 1697 "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute",
59eeb84b 1698 "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables",
cffaed83 1699 "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS",
3167f78a 1700 "CPUSchedulingResetOnFork", "NonBlocking", "LockPersonality")) {
506711fd
LP
1701 int b;
1702
1703 r = sd_bus_message_read(message, "b", &b);
1704 if (r < 0)
1705 return r;
1706
1707 if (mode != UNIT_CHECK) {
b9c50073
GP
1708 if (streq(name, "IgnoreSIGPIPE"))
1709 c->ignore_sigpipe = b;
1710 else if (streq(name, "TTYVHangup"))
1711 c->tty_vhangup = b;
1712 else if (streq(name, "TTYReset"))
1713 c->tty_reset = b;
cffaed83
YW
1714 else if (streq(name, "TTYVTDisallocate"))
1715 c->tty_vt_disallocate = b;
b9c50073
GP
1716 else if (streq(name, "PrivateTmp"))
1717 c->private_tmp = b;
1718 else if (streq(name, "PrivateDevices"))
1719 c->private_devices = b;
1720 else if (streq(name, "PrivateNetwork"))
1721 c->private_network = b;
d251207d
LP
1722 else if (streq(name, "PrivateUsers"))
1723 c->private_users = b;
b9c50073
GP
1724 else if (streq(name, "NoNewPrivileges"))
1725 c->no_new_privileges = b;
047d9933
EV
1726 else if (streq(name, "SyslogLevelPrefix"))
1727 c->syslog_level_prefix = b;
f3e43635
TM
1728 else if (streq(name, "MemoryDenyWriteExecute"))
1729 c->memory_deny_write_execute = b;
f4170c67
LP
1730 else if (streq(name, "RestrictRealtime"))
1731 c->restrict_realtime = b;
29206d46
LP
1732 else if (streq(name, "DynamicUser"))
1733 c->dynamic_user = b;
00d9ef85
LP
1734 else if (streq(name, "RemoveIPC"))
1735 c->remove_ipc = b;
59eeb84b
LP
1736 else if (streq(name, "ProtectKernelTunables"))
1737 c->protect_kernel_tunables = b;
502d704e
DH
1738 else if (streq(name, "ProtectKernelModules"))
1739 c->protect_kernel_modules = b;
59eeb84b
LP
1740 else if (streq(name, "ProtectControlGroups"))
1741 c->protect_control_groups = b;
5d997827
LP
1742 else if (streq(name, "MountAPIVFS"))
1743 c->mount_apivfs = b;
cffaed83
YW
1744 else if (streq(name, "CPUSchedulingResetOnFork"))
1745 c->cpu_sched_reset_on_fork = b;
1746 else if (streq(name, "NonBlocking"))
1747 c->non_blocking = b;
3167f78a
LP
1748 else if (streq(name, "LockPersonality"))
1749 c->lock_personality = b;
b9c50073 1750
b27b4b51 1751 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, yes_no(b));
506711fd
LP
1752 }
1753
1754 return 1;
1755
1756 } else if (streq(name, "UtmpIdentifier")) {
1757 const char *id;
1758
1759 r = sd_bus_message_read(message, "s", &id);
1760 if (r < 0)
1761 return r;
1762
1763 if (mode != UNIT_CHECK) {
76736280
LP
1764 if (isempty(id))
1765 c->utmp_id = mfree(c->utmp_id);
1766 else if (free_and_strdup(&c->utmp_id, id) < 0)
1767 return -ENOMEM;
506711fd 1768
b27b4b51 1769 unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s", strempty(id));
506711fd
LP
1770 }
1771
1772 return 1;
1773
1774 } else if (streq(name, "UtmpMode")) {
1775 const char *s;
1776 ExecUtmpMode m;
1777
1778 r = sd_bus_message_read(message, "s", &s);
1779 if (r < 0)
1780 return r;
1781
1782 m = exec_utmp_mode_from_string(s);
1783 if (m < 0)
1784 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
1785
1786 if (mode != UNIT_CHECK) {
1787 c->utmp_mode = m;
1788
b27b4b51 1789 unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s", exec_utmp_mode_to_string(m));
506711fd
LP
1790 }
1791
1792 return 1;
1793
1794 } else if (streq(name, "PAMName")) {
1795 const char *n;
1796
1797 r = sd_bus_message_read(message, "s", &n);
1798 if (r < 0)
1799 return r;
1800
1801 if (mode != UNIT_CHECK) {
76736280
LP
1802 if (isempty(n))
1803 c->pam_name = mfree(c->pam_name);
1804 else if (free_and_strdup(&c->pam_name, n) < 0)
1805 return -ENOMEM;
506711fd 1806
b27b4b51 1807 unit_write_drop_in_private_format(u, mode, name, "PAMName=%s", strempty(n));
506711fd
LP
1808 }
1809
1810 return 1;
1811
c7040b5d
LP
1812 } else if (streq(name, "Environment")) {
1813
f900f582 1814 _cleanup_strv_free_ char **l = NULL, **q = NULL;
c7040b5d
LP
1815
1816 r = sd_bus_message_read_strv(message, &l);
1817 if (r < 0)
1818 return r;
1819
1820 if (!strv_env_is_valid(l))
1821 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1822
f900f582
ZJS
1823 r = unit_full_printf_strv(u, l, &q);
1824 if (r < 0)
1825 return r;
c7040b5d 1826
f900f582
ZJS
1827 if (mode != UNIT_CHECK) {
1828 if (strv_length(q) == 0) {
e9876fc9 1829 c->environment = strv_free(c->environment);
b27b4b51 1830 unit_write_drop_in_private_format(u, mode, name, "Environment=");
e9876fc9 1831 } else {
f900f582
ZJS
1832 _cleanup_free_ char *joined = NULL;
1833 char **e;
1834
1835 e = strv_env_merge(2, c->environment, q);
e9876fc9
EV
1836 if (!e)
1837 return -ENOMEM;
c7040b5d 1838
e9876fc9
EV
1839 strv_free(c->environment);
1840 c->environment = e;
c7040b5d 1841
f900f582
ZJS
1842 /* We write just the new settings out to file, with unresolved specifiers */
1843 joined = strv_join_quoted(q);
e9876fc9
EV
1844 if (!joined)
1845 return -ENOMEM;
1846
b27b4b51 1847 unit_write_drop_in_private_format(u, mode, name, "Environment=%s", joined);
e9876fc9 1848 }
c7040b5d
LP
1849 }
1850
d584f638
LP
1851 return 1;
1852
00819cc1
LP
1853 } else if (streq(name, "UnsetEnvironment")) {
1854
1855 _cleanup_strv_free_ char **l = NULL, **q = NULL;
1856
1857 r = sd_bus_message_read_strv(message, &l);
1858 if (r < 0)
1859 return r;
1860
1861 r = unit_full_printf_strv(u, l, &q);
1862 if (r < 0)
1863 return r;
1864
1865 if (!strv_env_name_or_assignment_is_valid(q))
1866 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list.");
1867
1868 if (mode != UNIT_CHECK) {
1869 if (strv_length(q) == 0) {
1870 c->unset_environment = strv_free(c->unset_environment);
1871 unit_write_drop_in_private_format(u, mode, name, "UnsetEnvironment=");
1872 } else {
1873 _cleanup_free_ char *joined = NULL;
1874 char **e;
1875
1876 e = strv_env_merge(2, c->unset_environment, q);
1877 if (!e)
1878 return -ENOMEM;
1879
1880 strv_free(c->unset_environment);
1881 c->unset_environment = e;
1882
1883 /* We write just the new settings out to file, with unresolved specifiers */
1884 joined = strv_join_quoted(l);
1885 if (!joined)
1886 return -ENOMEM;
1887
1888 unit_write_drop_in_private_format(u, mode, name, "UnsetEnvironment=%s", joined);
1889 }
1890 }
1891
1892 return 1;
1893
f1db3327
EV
1894 } else if (streq(name, "TimerSlackNSec")) {
1895
1896 nsec_t n;
1897
1898 r = sd_bus_message_read(message, "t", &n);
1899 if (r < 0)
1900 return r;
1901
1902 if (mode != UNIT_CHECK) {
1903 c->timer_slack_nsec = n;
b27b4b51 1904 unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT, n);
f1db3327
EV
1905 }
1906
1907 return 1;
1908
6b862936
EV
1909 } else if (streq(name, "OOMScoreAdjust")) {
1910 int oa;
1911
1912 r = sd_bus_message_read(message, "i", &oa);
1913 if (r < 0)
1914 return r;
1915
1916 if (!oom_score_adjust_is_valid(oa))
1917 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
1918
1919 if (mode != UNIT_CHECK) {
1920 c->oom_score_adjust = oa;
1921 c->oom_score_adjust_set = true;
b27b4b51 1922 unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i", oa);
6b862936
EV
1923 }
1924
1925 return 1;
1926
ceb728cf
NC
1927 } else if (streq(name, "EnvironmentFiles")) {
1928
1929 _cleanup_free_ char *joined = NULL;
1930 _cleanup_fclose_ FILE *f = NULL;
9b531f04 1931 _cleanup_strv_free_ char **l = NULL;
ceb728cf 1932 size_t size = 0;
2229f656 1933 char **i;
ceb728cf
NC
1934
1935 r = sd_bus_message_enter_container(message, 'a', "(sb)");
1936 if (r < 0)
1937 return r;
1938
1939 f = open_memstream(&joined, &size);
1940 if (!f)
1941 return -ENOMEM;
1942
2229f656 1943 STRV_FOREACH(i, c->environment_files)
b27b4b51 1944 fprintf(f, "EnvironmentFile=%s", *i);
ceb728cf
NC
1945
1946 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
1947 const char *path;
1948 int b;
1949
ceb728cf
NC
1950 r = sd_bus_message_read(message, "sb", &path, &b);
1951 if (r < 0)
1952 return r;
1953
1954 r = sd_bus_message_exit_container(message);
1955 if (r < 0)
1956 return r;
1957
d2d6c096
LP
1958 if (!path_is_absolute(path))
1959 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
ceb728cf
NC
1960
1961 if (mode != UNIT_CHECK) {
ae978b9f 1962 char *buf;
ceb728cf 1963
605405c6 1964 buf = strjoin(b ? "-" : "", path);
2229f656 1965 if (!buf)
ceb728cf
NC
1966 return -ENOMEM;
1967
b27b4b51 1968 fprintf(f, "EnvironmentFile=%s", buf);
ceb728cf 1969
2229f656 1970 r = strv_consume(&l, buf);
ceb728cf
NC
1971 if (r < 0)
1972 return r;
1973 }
1974 }
1975 if (r < 0)
1976 return r;
1977
b0830e21
LP
1978 r = sd_bus_message_exit_container(message);
1979 if (r < 0)
1980 return r;
1981
2229f656
LP
1982 r = fflush_and_check(f);
1983 if (r < 0)
1984 return r;
ceb728cf 1985
2229f656
LP
1986 if (mode != UNIT_CHECK) {
1987 if (strv_isempty(l)) {
1988 c->environment_files = strv_free(c->environment_files);
b27b4b51 1989 unit_write_drop_in_private(u, mode, name, "EnvironmentFile=");
2229f656
LP
1990 } else {
1991 r = strv_extend_strv(&c->environment_files, l, true);
1992 if (r < 0)
1993 return r;
1994
ceb728cf 1995 unit_write_drop_in_private(u, mode, name, joined);
2229f656
LP
1996 }
1997 }
ceb728cf 1998
ceb728cf
NC
1999 return 1;
2000
b4c14404
FB
2001 } else if (streq(name, "PassEnvironment")) {
2002
2003 _cleanup_strv_free_ char **l = NULL;
2004
2005 r = sd_bus_message_read_strv(message, &l);
2006 if (r < 0)
2007 return r;
2008
2009 if (!strv_env_name_is_valid(l))
00819cc1 2010 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block.");
b4c14404
FB
2011
2012 if (mode != UNIT_CHECK) {
2013 if (strv_isempty(l)) {
2014 c->pass_environment = strv_free(c->pass_environment);
b27b4b51 2015 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=");
b4c14404
FB
2016 } else {
2017 _cleanup_free_ char *joined = NULL;
2018
2019 r = strv_extend_strv(&c->pass_environment, l, true);
2020 if (r < 0)
2021 return r;
2022
2023 joined = strv_join_quoted(c->pass_environment);
2024 if (!joined)
2025 return -ENOMEM;
2026
b27b4b51 2027 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=%s", joined);
b4c14404
FB
2028 }
2029 }
2030
2031 return 1;
2032
2a624c36
AP
2033 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
2034 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) {
08596068
EV
2035 _cleanup_strv_free_ char **l = NULL;
2036 char ***dirs;
2037 char **p;
2038
2039 r = sd_bus_message_read_strv(message, &l);
2040 if (r < 0)
2041 return r;
2042
2043 STRV_FOREACH(p, l) {
20b7a007
LP
2044 const char *i = *p;
2045 size_t offset;
2046
2047 if (!utf8_is_valid(i))
08596068
EV
2048 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
2049
20b7a007
LP
2050 offset = i[0] == '-';
2051 offset += i[offset] == '+';
2052 if (!path_is_absolute(i + offset))
08596068
EV
2053 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
2054 }
2055
2056 if (mode != UNIT_CHECK) {
2057 _cleanup_free_ char *joined = NULL;
2058
c4b41707
AP
2059 if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths"))
2060 dirs = &c->read_write_paths;
2061 else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
2062 dirs = &c->read_only_paths;
2063 else /* "InaccessiblePaths" */
2064 dirs = &c->inaccessible_paths;
08596068
EV
2065
2066 if (strv_length(l) == 0) {
2067 *dirs = strv_free(*dirs);
b27b4b51 2068 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
08596068
EV
2069 } else {
2070 r = strv_extend_strv(dirs, l, true);
08596068
EV
2071 if (r < 0)
2072 return -ENOMEM;
2073
2074 joined = strv_join_quoted(*dirs);
2075 if (!joined)
2076 return -ENOMEM;
2077
b27b4b51 2078 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
08596068
EV
2079 }
2080
2081 }
2082
2083 return 1;
2084
5664e6cf
EV
2085 } else if (streq(name, "ProtectSystem")) {
2086 const char *s;
2087 ProtectSystem ps;
2088
2089 r = sd_bus_message_read(message, "s", &s);
2090 if (r < 0)
2091 return r;
2092
2093 r = parse_boolean(s);
2094 if (r > 0)
2095 ps = PROTECT_SYSTEM_YES;
2096 else if (r == 0)
2097 ps = PROTECT_SYSTEM_NO;
2098 else {
2099 ps = protect_system_from_string(s);
2100 if (ps < 0)
2101 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value");
2102 }
2103
2104 if (mode != UNIT_CHECK) {
2105 c->protect_system = ps;
b27b4b51 2106 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
5664e6cf
EV
2107 }
2108
2109 return 1;
2110
eff58074
EV
2111 } else if (streq(name, "ProtectHome")) {
2112 const char *s;
2113 ProtectHome ph;
2114
2115 r = sd_bus_message_read(message, "s", &s);
2116 if (r < 0)
2117 return r;
2118
2119 r = parse_boolean(s);
2120 if (r > 0)
2121 ph = PROTECT_HOME_YES;
2122 else if (r == 0)
2123 ph = PROTECT_HOME_NO;
2124 else {
2125 ph = protect_home_from_string(s);
2126 if (ph < 0)
2127 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value");
2128 }
2129
2130 if (mode != UNIT_CHECK) {
2131 c->protect_home = ph;
b27b4b51 2132 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
eff58074
EV
2133 }
2134
2135 return 1;
2136
53f47dfc
YW
2137 } else if (streq(name, "RuntimeDirectoryPreserve")) {
2138 const char *s;
2139 ExecPreserveMode m;
2140
2141 r = sd_bus_message_read(message, "s", &s);
2142 if (r < 0)
2143 return r;
2144
2145 m = exec_preserve_mode_from_string(s);
2146 if (m < 0)
2147 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid preserve mode");
2148
2149 if (mode != UNIT_CHECK) {
2150 c->runtime_directory_preserve_mode = m;
2151
2152 unit_write_drop_in_private_format(u, mode, name, "RuntimeDirectoryPreserve=%s", exec_preserve_mode_to_string(m));
2153 }
2154
2155 return 1;
2156
cffaed83 2157 } else if (STR_IN_SET(name, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode", "UMask")) {
53f47dfc
YW
2158 mode_t m;
2159
2160 r = sd_bus_message_read(message, "u", &m);
2161 if (r < 0)
2162 return r;
2163
2164 if (mode != UNIT_CHECK) {
3536f49e 2165 ExecDirectoryType i;
53f47dfc 2166
cffaed83
YW
2167 if (streq(name, "UMask"))
2168 c->umask = m;
2169 else
2170 for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
2171 if (startswith(name, exec_directory_type_to_string(i))) {
2172 c->directories[i].mode = m;
2173 break;
2174 }
3536f49e
YW
2175
2176 unit_write_drop_in_private_format(u, mode, name, "%s=%040o", name, m);
53f47dfc
YW
2177 }
2178
2179 return 1;
2180
3536f49e 2181 } else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
fa21b5e3
EV
2182 _cleanup_strv_free_ char **l = NULL;
2183 char **p;
2184
2185 r = sd_bus_message_read_strv(message, &l);
2186 if (r < 0)
2187 return r;
2188
2189 STRV_FOREACH(p, l) {
2190 if (!filename_is_valid(*p))
3536f49e 2191 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s is not valid %s", name, *p);
fa21b5e3
EV
2192 }
2193
2194 if (mode != UNIT_CHECK) {
2195 _cleanup_free_ char *joined = NULL;
3536f49e
YW
2196 char ***dirs = NULL;
2197 ExecDirectoryType i;
2198
2199 for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
2200 if (streq(name, exec_directory_type_to_string(i))) {
2201 dirs = &c->directories[i].paths;
2202 break;
2203 }
2204
2205 assert(dirs);
fa21b5e3
EV
2206
2207 if (strv_isempty(l)) {
3536f49e 2208 *dirs = strv_free(*dirs);
b27b4b51 2209 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
fa21b5e3 2210 } else {
3536f49e 2211 r = strv_extend_strv(dirs, l, true);
fa21b5e3
EV
2212
2213 if (r < 0)
2214 return -ENOMEM;
2215
3536f49e 2216 joined = strv_join_quoted(*dirs);
fa21b5e3
EV
2217 if (!joined)
2218 return -ENOMEM;
2219
b27b4b51 2220 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
fa21b5e3
EV
2221 }
2222 }
2223
2224 return 1;
2225
186ad4b1
JB
2226 } else if (streq(name, "SELinuxContext")) {
2227 const char *s;
186ad4b1
JB
2228 r = sd_bus_message_read(message, "s", &s);
2229 if (r < 0)
2230 return r;
2231
2232 if (mode != UNIT_CHECK) {
4e282d11
JB
2233 if (isempty(s))
2234 c->selinux_context = mfree(c->selinux_context);
2235 else if (free_and_strdup(&c->selinux_context, s) < 0)
2236 return -ENOMEM;
186ad4b1 2237
b27b4b51 2238 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, strempty(s));
186ad4b1
JB
2239 }
2240
2241 return 1;
cffaed83
YW
2242
2243 } else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
2244 int ignore;
2245 const char *s;
2246
2247 r = sd_bus_message_enter_container(message, 'r', "bs");
2248 if (r < 0)
2249 return r;
2250
2251 r = sd_bus_message_read(message, "bs", &ignore, &s);
2252 if (r < 0)
2253 return r;
2254
2255 if (mode != UNIT_CHECK) {
2256 char **p;
2257 bool *b;
2258
2259 if (streq(name, "AppArmorProfile")) {
2260 p = &c->apparmor_profile;
2261 b = &c->apparmor_profile_ignore;
2262 } else { /* "SmackProcessLabel" */
2263 p = &c->smack_process_label;
2264 b = &c->smack_process_label_ignore;
2265 }
2266
2267 if (isempty(s)) {
2268 *p = mfree(*p);
2269 *b = false;
2270 } else {
2271 if (free_and_strdup(p, s) < 0)
2272 return -ENOMEM;
2273 *b = ignore;
2274 }
2275
2276 unit_write_drop_in_private_format(u, mode, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
2277 }
2278
2279 return 1;
2280
add00535
LP
2281 } else if (streq(name, "RestrictNamespaces")) {
2282 uint64_t flags;
186ad4b1 2283
add00535
LP
2284 r = sd_bus_message_read(message, "t", &flags);
2285 if (r < 0)
2286 return r;
2287 if ((flags & NAMESPACE_FLAGS_ALL) != flags)
2288 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown namespace types");
2289
2290 if (mode != UNIT_CHECK) {
2291 _cleanup_free_ char *s = NULL;
2292
2293 r = namespace_flag_to_string_many(flags, &s);
2294 if (r < 0)
2295 return r;
2296
2297 c->restrict_namespaces = flags;
2298 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
2299 }
2300
2301 return 1;
83555251
LP
2302 } else if (streq(name, "MountFlags")) {
2303 uint64_t flags;
2304
2305 r = sd_bus_message_read(message, "t", &flags);
2306 if (r < 0)
2307 return r;
2308 if (!IN_SET(flags, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
2309 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount propagation flags");
cab2aca3 2310
83555251
LP
2311 if (mode != UNIT_CHECK) {
2312 c->mount_flags = flags;
2313
c7383828 2314 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, mount_propagation_flags_to_string(flags));
83555251
LP
2315 }
2316
d2d6c096
LP
2317 return 1;
2318 } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
2319 unsigned empty = true;
2320
2321 r = sd_bus_message_enter_container(message, 'a', "(ssbt)");
2322 if (r < 0)
2323 return r;
2324
2325 while ((r = sd_bus_message_enter_container(message, 'r', "ssbt")) > 0) {
2326 const char *source, *destination;
2327 int ignore_enoent;
2328 uint64_t mount_flags;
2329
2330 r = sd_bus_message_read(message, "ssbt", &source, &destination, &ignore_enoent, &mount_flags);
2331 if (r < 0)
2332 return r;
2333
2334 r = sd_bus_message_exit_container(message);
2335 if (r < 0)
2336 return r;
2337
2338 if (!path_is_absolute(source))
2339 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
2340 if (!path_is_absolute(destination))
91d910e3 2341 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
d2d6c096
LP
2342 if (!IN_SET(mount_flags, 0, MS_REC))
2343 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
2344
2345 if (mode != UNIT_CHECK) {
2346 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
2347 &(BindMount) {
2348 .source = strdup(source),
2349 .destination = strdup(destination),
2350 .read_only = !!strstr(name, "ReadOnly"),
2351 .recursive = !!(mount_flags & MS_REC),
2352 .ignore_enoent = ignore_enoent,
2353 });
2354 if (r < 0)
2355 return r;
2356
2357 unit_write_drop_in_private_format(
2358 u, mode, name,
2359 "%s=%s%s:%s:%s",
2360 name,
2361 ignore_enoent ? "-" : "",
2362 source,
2363 destination,
2364 (mount_flags & MS_REC) ? "rbind" : "norbind");
2365 }
2366
2367 empty = false;
2368 }
2369 if (r < 0)
2370 return r;
2371
2372 r = sd_bus_message_exit_container(message);
2373 if (r < 0)
2374 return r;
2375
2376 if (empty) {
2377 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
2378 c->bind_mounts = NULL;
2379 c->n_bind_mounts = 0;
2380 }
2381
83555251
LP
2382 return 1;
2383 }
d2d6c096 2384
cab2aca3
LP
2385 ri = rlimit_from_string(name);
2386 if (ri < 0) {
2387 soft = endswith(name, "Soft");
2388 if (soft) {
2389 const char *n;
2390
2391 n = strndupa(name, soft - name);
2392 ri = rlimit_from_string(n);
2393 if (ri >= 0)
2394 name = n;
2395
2396 }
2397 }
2398
2399 if (ri >= 0) {
d584f638
LP
2400 uint64_t rl;
2401 rlim_t x;
2402
2403 r = sd_bus_message_read(message, "t", &rl);
2404 if (r < 0)
2405 return r;
2406
2407 if (rl == (uint64_t) -1)
2408 x = RLIM_INFINITY;
2409 else {
2410 x = (rlim_t) rl;
2411
2412 if ((uint64_t) x != rl)
2413 return -ERANGE;
2414 }
2415
2416 if (mode != UNIT_CHECK) {
cab2aca3
LP
2417 _cleanup_free_ char *f = NULL;
2418 struct rlimit nl;
2419
2420 if (c->rlimit[ri]) {
2421 nl = *c->rlimit[ri];
2422
2423 if (soft)
2424 nl.rlim_cur = x;
2425 else
2426 nl.rlim_max = x;
2427 } else
2428 /* When the resource limit is not initialized yet, then assign the value to both fields */
2429 nl = (struct rlimit) {
2430 .rlim_cur = x,
2431 .rlim_max = x,
2432 };
2433
2434 r = rlimit_format(&nl, &f);
2435 if (r < 0)
2436 return r;
d584f638 2437
cab2aca3
LP
2438 if (c->rlimit[ri])
2439 *c->rlimit[ri] = nl;
2440 else {
2441 c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
2442 if (!c->rlimit[ri])
d584f638
LP
2443 return -ENOMEM;
2444 }
2445
b27b4b51 2446 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, f);
d584f638
LP
2447 }
2448
c7040b5d
LP
2449 return 1;
2450 }
2451
2452 return 0;
2453}