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