]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
tree-wide: use the same comment for work-around initializations
[thirdparty/systemd.git] / src / core / dbus-execute.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
4139c1b2 2
227b8a76 3#include <sys/mount.h>
82c121a4 4#include <sys/prctl.h>
4139c1b2 5
349cc4a5 6#if HAVE_SECCOMP
57183d11
LP
7#include <seccomp.h>
8#endif
9
3ffd4af2 10#include "af-list.h"
b5efdb8a 11#include "alloc-util.h"
40af3d02 12#include "bus-get-properties.h"
cffaed83 13#include "cap-list.h"
d3070fbd 14#include "capability-util.h"
501941aa 15#include "cpu-set-util.h"
786d19fd 16#include "creds-util.h"
3ffd4af2 17#include "dbus-execute.h"
7e2a3fcc 18#include "dbus-util.h"
c7040b5d 19#include "env-util.h"
cffaed83 20#include "errno-list.h"
2e59b241 21#include "escape.h"
3ffd4af2
LP
22#include "execute.h"
23#include "fd-util.h"
24#include "fileio.h"
08f3be7a 25#include "hexdecoct.h"
d3070fbd 26#include "io-util.h"
3ffd4af2 27#include "ioprio.h"
adce225a 28#include "journal-file.h"
049af8ad 29#include "mountpoint-util.h"
417116f2 30#include "namespace.h"
6bedfcbb 31#include "parse-util.h"
9b15b784 32#include "path-util.h"
7b3e062c 33#include "process-util.h"
78f22b97 34#include "rlimit-util.h"
349cc4a5 35#if HAVE_SECCOMP
57183d11
LP
36#include "seccomp-util.h"
37#endif
cffaed83 38#include "securebits-util.h"
2e59b241 39#include "specifier.h"
6bedfcbb 40#include "strv.h"
7ccbd1ae 41#include "syslog-util.h"
f900f582 42#include "unit-printf.h"
6f3e7985 43#include "user-util.h"
6bedfcbb 44#include "utf8.h"
57183d11 45
718db961 46BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
718db961 47static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
023a4f67 48static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
53f47dfc 49static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
b1edf445 50static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode);
4e399953
LP
51static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_proc, protect_proc, ProtectProc);
52static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_proc_subset, proc_subset, ProcSubset);
73b84e92
YW
53static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_home, protect_home, ProtectHome);
54static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system, protect_system, ProtectSystem);
491eecb3 55static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality, personality, unsigned long);
019b34ca 56static BUS_DEFINE_PROPERTY_GET(property_get_ioprio, "i", ExecContext, exec_context_get_effective_ioprio);
5e98086d 57static BUS_DEFINE_PROPERTY_GET(property_get_mount_apivfs, "b", ExecContext, exec_context_get_effective_mount_apivfs);
019b34ca
YW
58static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_class, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_CLASS);
59static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_DATA);
92c23c5a
YW
60static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL);
61static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI);
62static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC);
e2b2fb7f
MS
63static BUS_DEFINE_PROPERTY_GET(property_get_cpu_affinity_from_numa, "b", ExecContext, exec_context_get_cpu_affinity_from_numa);
64
718db961
LP
65static int property_get_environment_files(
66 sd_bus *bus,
67 const char *path,
68 const char *interface,
69 const char *property,
70 sd_bus_message *reply,
ebcf1f97
LP
71 void *userdata,
72 sd_bus_error *error) {
8c7be95e 73
718db961
LP
74 ExecContext *c = userdata;
75 char **j;
76 int r;
8c7be95e 77
718db961
LP
78 assert(bus);
79 assert(reply);
80 assert(c);
81
82 r = sd_bus_message_open_container(reply, 'a', "(sb)");
83 if (r < 0)
84 return r;
8c7be95e 85
718db961
LP
86 STRV_FOREACH(j, c->environment_files) {
87 const char *fn = *j;
8c7be95e 88
718db961
LP
89 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
90 if (r < 0)
91 return r;
8c7be95e
LP
92 }
93
718db961
LP
94 return sd_bus_message_close_container(reply);
95}
96
718db961
LP
97static int property_get_oom_score_adjust(
98 sd_bus *bus,
99 const char *path,
100 const char *interface,
101 const char *property,
102 sd_bus_message *reply,
ebcf1f97
LP
103 void *userdata,
104 sd_bus_error *error) {
718db961 105
718db961 106 ExecContext *c = userdata;
82c121a4 107 int32_t n;
b94fb74b 108 int r;
82c121a4 109
718db961
LP
110 assert(bus);
111 assert(reply);
82c121a4
LP
112 assert(c);
113
dd6c17b1
LP
114 if (c->oom_score_adjust_set)
115 n = c->oom_score_adjust;
82c121a4 116 else {
68eda4bd 117 _cleanup_free_ char *t = NULL;
82c121a4
LP
118
119 n = 0;
b94fb74b
ZJS
120 r = read_one_line_file("/proc/self/oom_score_adj", &t);
121 if (r < 0)
122 log_debug_errno(r, "Failed to read /proc/self/oom_score_adj, ignoring: %m");
123 else {
124 r = safe_atoi32(t, &n);
125 if (r < 0)
126 log_debug_errno(r, "Failed to parse \"%s\" from /proc/self/oom_score_adj, ignoring: %m", t);
127 }
82c121a4
LP
128 }
129
718db961 130 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
131}
132
ad21e542
ZJS
133static int property_get_coredump_filter(
134 sd_bus *bus,
135 const char *path,
136 const char *interface,
137 const char *property,
138 sd_bus_message *reply,
139 void *userdata,
140 sd_bus_error *error) {
141
142 ExecContext *c = userdata;
143 uint64_t n;
144 int r;
145
146 assert(bus);
147 assert(reply);
148 assert(c);
149
150 if (c->coredump_filter_set)
151 n = c->coredump_filter;
152 else {
153 _cleanup_free_ char *t = NULL;
154
155 n = COREDUMP_FILTER_MASK_DEFAULT;
156 r = read_one_line_file("/proc/self/coredump_filter", &t);
157 if (r < 0)
158 log_debug_errno(r, "Failed to read /proc/self/coredump_filter, ignoring: %m");
159 else {
160 r = safe_atoux64(t, &n);
161 if (r < 0)
162 log_debug_errno(r, "Failed to parse \"%s\" from /proc/self/coredump_filter, ignoring: %m", t);
163 }
164 }
165
166 return sd_bus_message_append(reply, "t", n);
167}
168
718db961
LP
169static int property_get_nice(
170 sd_bus *bus,
171 const char *path,
172 const char *interface,
173 const char *property,
174 sd_bus_message *reply,
ebcf1f97
LP
175 void *userdata,
176 sd_bus_error *error) {
718db961 177
718db961 178 ExecContext *c = userdata;
82c121a4
LP
179 int32_t n;
180
718db961
LP
181 assert(bus);
182 assert(reply);
82c121a4
LP
183 assert(c);
184
185 if (c->nice_set)
186 n = c->nice;
718db961
LP
187 else {
188 errno = 0;
82c121a4 189 n = getpriority(PRIO_PROCESS, 0);
b3267152 190 if (errno > 0)
718db961
LP
191 n = 0;
192 }
82c121a4 193
718db961 194 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
195}
196
718db961
LP
197static int property_get_cpu_sched_policy(
198 sd_bus *bus,
199 const char *path,
200 const char *interface,
201 const char *property,
202 sd_bus_message *reply,
ebcf1f97
LP
203 void *userdata,
204 sd_bus_error *error) {
718db961
LP
205
206 ExecContext *c = userdata;
82c121a4
LP
207 int32_t n;
208
718db961
LP
209 assert(bus);
210 assert(reply);
82c121a4
LP
211 assert(c);
212
213 if (c->cpu_sched_set)
214 n = c->cpu_sched_policy;
718db961 215 else {
82c121a4 216 n = sched_getscheduler(0);
718db961
LP
217 if (n < 0)
218 n = SCHED_OTHER;
219 }
82c121a4 220
718db961 221 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
222}
223
718db961
LP
224static int property_get_cpu_sched_priority(
225 sd_bus *bus,
226 const char *path,
227 const char *interface,
228 const char *property,
229 sd_bus_message *reply,
ebcf1f97
LP
230 void *userdata,
231 sd_bus_error *error) {
718db961
LP
232
233 ExecContext *c = userdata;
82c121a4
LP
234 int32_t n;
235
718db961
LP
236 assert(bus);
237 assert(reply);
82c121a4
LP
238 assert(c);
239
240 if (c->cpu_sched_set)
241 n = c->cpu_sched_priority;
242 else {
b92bea5d 243 struct sched_param p = {};
82c121a4 244
82c121a4
LP
245 if (sched_getparam(0, &p) >= 0)
246 n = p.sched_priority;
e62d8c39
ZJS
247 else
248 n = 0;
82c121a4
LP
249 }
250
718db961 251 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
252}
253
718db961
LP
254static int property_get_cpu_affinity(
255 sd_bus *bus,
256 const char *path,
257 const char *interface,
258 const char *property,
259 sd_bus_message *reply,
ebcf1f97
LP
260 void *userdata,
261 sd_bus_error *error) {
82c121a4 262
718db961 263 ExecContext *c = userdata;
e2b2fb7f 264 _cleanup_(cpu_set_reset) CPUSet s = {};
75e40119
MS
265 _cleanup_free_ uint8_t *array = NULL;
266 size_t allocated;
82c121a4 267
718db961
LP
268 assert(bus);
269 assert(reply);
270 assert(c);
82c121a4 271
e2b2fb7f
MS
272 if (c->cpu_affinity_from_numa) {
273 int r;
274
275 r = numa_to_cpu_set(&c->numa_policy, &s);
276 if (r < 0)
277 return r;
278 }
279
280 (void) cpu_set_to_dbus(c->cpu_affinity_from_numa ? &s : &c->cpu_set, &array, &allocated);
281
75e40119 282 return sd_bus_message_append_array(reply, 'y', array, allocated);
82c121a4
LP
283}
284
b070c7c0
MS
285static int property_get_numa_mask(
286 sd_bus *bus,
287 const char *path,
288 const char *interface,
289 const char *property,
290 sd_bus_message *reply,
291 void *userdata,
292 sd_bus_error *error) {
293
294 ExecContext *c = userdata;
295 _cleanup_free_ uint8_t *array = NULL;
296 size_t allocated;
297
298 assert(bus);
299 assert(reply);
300 assert(c);
301
302 (void) cpu_set_to_dbus(&c->numa_policy.nodes, &array, &allocated);
303
304 return sd_bus_message_append_array(reply, 'y', array, allocated);
305}
306
307static int property_get_numa_policy(
308 sd_bus *bus,
309 const char *path,
310 const char *interface,
311 const char *property,
312 sd_bus_message *reply,
313 void *userdata,
314 sd_bus_error *error) {
315 ExecContext *c = userdata;
316 int32_t policy;
317
318 assert(bus);
319 assert(reply);
320 assert(c);
321
322 policy = numa_policy_get_type(&c->numa_policy);
323
324 return sd_bus_message_append_basic(reply, 'i', &policy);
325}
326
718db961
LP
327static int property_get_timer_slack_nsec(
328 sd_bus *bus,
329 const char *path,
330 const char *interface,
331 const char *property,
332 sd_bus_message *reply,
ebcf1f97
LP
333 void *userdata,
334 sd_bus_error *error) {
718db961
LP
335
336 ExecContext *c = userdata;
82c121a4
LP
337 uint64_t u;
338
718db961
LP
339 assert(bus);
340 assert(reply);
82c121a4
LP
341 assert(c);
342
3a43da28 343 if (c->timer_slack_nsec != NSEC_INFINITY)
03fae018 344 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
345 else
346 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
347
718db961 348 return sd_bus_message_append(reply, "t", u);
82c121a4
LP
349}
350
718db961
LP
351static int property_get_syscall_filter(
352 sd_bus *bus,
353 const char *path,
354 const char *interface,
355 const char *property,
356 sd_bus_message *reply,
ebcf1f97
LP
357 void *userdata,
358 sd_bus_error *error) {
82c121a4 359
17df7223
LP
360 ExecContext *c = userdata;
361 _cleanup_strv_free_ char **l = NULL;
57183d11
LP
362 int r;
363
349cc4a5 364#if HAVE_SECCOMP
8cfa775f 365 void *id, *val;
351a19b1 366#endif
17df7223
LP
367
368 assert(bus);
369 assert(reply);
370 assert(c);
371
57183d11
LP
372 r = sd_bus_message_open_container(reply, 'r', "bas");
373 if (r < 0)
374 return r;
375
6b000af4 376 r = sd_bus_message_append(reply, "b", c->syscall_allow_list);
57183d11
LP
377 if (r < 0)
378 return r;
379
349cc4a5 380#if HAVE_SECCOMP
90e74a66 381 HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) {
8cfa775f
YW
382 _cleanup_free_ char *name = NULL;
383 const char *e = NULL;
384 char *s;
385 int num = PTR_TO_INT(val);
17df7223
LP
386
387 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
388 if (!name)
389 continue;
390
8cfa775f 391 if (num >= 0) {
005bfaf1 392 e = seccomp_errno_or_action_to_string(num);
8cfa775f
YW
393 if (e) {
394 s = strjoin(name, ":", e);
395 if (!s)
396 return -ENOMEM;
397 } else {
398 r = asprintf(&s, "%s:%d", name, num);
399 if (r < 0)
400 return -ENOMEM;
401 }
ae2a15bc
LP
402 } else
403 s = TAKE_PTR(name);
8cfa775f
YW
404
405 r = strv_consume(&l, s);
6e18964d
ZJS
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
9df2cdd8
TM
420static int property_get_syscall_log(
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#if HAVE_SECCOMP
434 void *id, *val;
435#endif
436
437 assert(bus);
438 assert(reply);
439 assert(c);
440
441 r = sd_bus_message_open_container(reply, 'r', "bas");
442 if (r < 0)
443 return r;
444
445 r = sd_bus_message_append(reply, "b", c->syscall_log_allow_list);
446 if (r < 0)
447 return r;
448
449#if HAVE_SECCOMP
450 HASHMAP_FOREACH_KEY(val, id, c->syscall_log) {
451 char *name = NULL;
452
453 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
454 if (!name)
455 continue;
456
457 r = strv_consume(&l, name);
458 if (r < 0)
459 return r;
460 }
461#endif
462
463 strv_sort(l);
464
465 r = sd_bus_message_append_strv(reply, l);
466 if (r < 0)
467 return r;
468
469 return sd_bus_message_close_container(reply);
470}
471
57183d11
LP
472static int property_get_syscall_archs(
473 sd_bus *bus,
474 const char *path,
475 const char *interface,
476 const char *property,
477 sd_bus_message *reply,
478 void *userdata,
479 sd_bus_error *error) {
480
481 ExecContext *c = userdata;
482 _cleanup_strv_free_ char **l = NULL;
483 int r;
484
349cc4a5 485#if HAVE_SECCOMP
57183d11
LP
486 void *id;
487#endif
488
489 assert(bus);
490 assert(reply);
491 assert(c);
17df7223 492
349cc4a5 493#if HAVE_SECCOMP
90e74a66 494 SET_FOREACH(id, c->syscall_archs) {
57183d11
LP
495 const char *name;
496
497 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
498 if (!name)
499 continue;
500
501 r = strv_extend(&l, name);
502 if (r < 0)
503 return -ENOMEM;
17df7223 504 }
57183d11
LP
505#endif
506
507 strv_sort(l);
508
509 r = sd_bus_message_append_strv(reply, l);
510 if (r < 0)
511 return r;
17df7223 512
57183d11 513 return 0;
17df7223
LP
514}
515
5f8640fb
LP
516static int property_get_selinux_context(
517 sd_bus *bus,
518 const char *path,
519 const char *interface,
520 const char *property,
521 sd_bus_message *reply,
522 void *userdata,
523 sd_bus_error *error) {
524
525 ExecContext *c = userdata;
526
527 assert(bus);
528 assert(reply);
529 assert(c);
530
531 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
532}
533
eef65bf3
MS
534static int property_get_apparmor_profile(
535 sd_bus *bus,
536 const char *path,
537 const char *interface,
538 const char *property,
539 sd_bus_message *reply,
540 void *userdata,
541 sd_bus_error *error) {
542
543 ExecContext *c = userdata;
544
545 assert(bus);
546 assert(reply);
547 assert(c);
548
549 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
550}
551
2ca620c4
WC
552static int property_get_smack_process_label(
553 sd_bus *bus,
554 const char *path,
555 const char *interface,
556 const char *property,
557 sd_bus_message *reply,
558 void *userdata,
559 sd_bus_error *error) {
560
561 ExecContext *c = userdata;
562
563 assert(bus);
564 assert(reply);
565 assert(c);
566
567 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
568}
569
4298d0b5
LP
570static int property_get_address_families(
571 sd_bus *bus,
572 const char *path,
573 const char *interface,
574 const char *property,
575 sd_bus_message *reply,
576 void *userdata,
577 sd_bus_error *error) {
578
579 ExecContext *c = userdata;
580 _cleanup_strv_free_ char **l = NULL;
4298d0b5
LP
581 void *af;
582 int r;
583
584 assert(bus);
585 assert(reply);
586 assert(c);
587
588 r = sd_bus_message_open_container(reply, 'r', "bas");
589 if (r < 0)
590 return r;
591
6b000af4 592 r = sd_bus_message_append(reply, "b", c->address_families_allow_list);
4298d0b5
LP
593 if (r < 0)
594 return r;
595
90e74a66 596 SET_FOREACH(af, c->address_families) {
4298d0b5
LP
597 const char *name;
598
599 name = af_to_name(PTR_TO_INT(af));
600 if (!name)
601 continue;
602
603 r = strv_extend(&l, name);
604 if (r < 0)
605 return -ENOMEM;
606 }
607
608 strv_sort(l);
609
610 r = sd_bus_message_append_strv(reply, l);
611 if (r < 0)
612 return r;
613
614 return sd_bus_message_close_container(reply);
615}
616
5f5d8eab
LP
617static int property_get_working_directory(
618 sd_bus *bus,
619 const char *path,
620 const char *interface,
621 const char *property,
622 sd_bus_message *reply,
623 void *userdata,
624 sd_bus_error *error) {
625
626 ExecContext *c = userdata;
627 const char *wd;
628
629 assert(bus);
630 assert(reply);
631 assert(c);
632
633 if (c->working_directory_home)
634 wd = "~";
635 else
636 wd = c->working_directory;
637
638 if (c->working_directory_missing_ok)
639 wd = strjoina("!", wd);
640
641 return sd_bus_message_append(reply, "s", wd);
642}
643
5073ff6b 644static int property_get_stdio_fdname(
52c239d7
LB
645 sd_bus *bus,
646 const char *path,
647 const char *interface,
648 const char *property,
649 sd_bus_message *reply,
650 void *userdata,
651 sd_bus_error *error) {
652
653 ExecContext *c = userdata;
5073ff6b 654 int fileno;
52c239d7
LB
655
656 assert(bus);
657 assert(c);
658 assert(property);
659 assert(reply);
660
5073ff6b
LP
661 if (streq(property, "StandardInputFileDescriptorName"))
662 fileno = STDIN_FILENO;
663 else if (streq(property, "StandardOutputFileDescriptorName"))
664 fileno = STDOUT_FILENO;
665 else {
666 assert(streq(property, "StandardErrorFileDescriptorName"));
667 fileno = STDERR_FILENO;
668 }
52c239d7 669
5073ff6b 670 return sd_bus_message_append(reply, "s", exec_context_fdname(c, fileno));
52c239d7
LB
671}
672
08f3be7a 673static int property_get_input_data(
52c239d7
LB
674 sd_bus *bus,
675 const char *path,
676 const char *interface,
677 const char *property,
678 sd_bus_message *reply,
679 void *userdata,
680 sd_bus_error *error) {
681
682 ExecContext *c = userdata;
52c239d7
LB
683
684 assert(bus);
685 assert(c);
686 assert(property);
687 assert(reply);
688
08f3be7a 689 return sd_bus_message_append_array(reply, 'y', c->stdin_data, c->stdin_data_size);
52c239d7
LB
690}
691
d2d6c096
LP
692static int property_get_bind_paths(
693 sd_bus *bus,
694 const char *path,
695 const char *interface,
696 const char *property,
697 sd_bus_message *reply,
698 void *userdata,
699 sd_bus_error *error) {
700
701 ExecContext *c = userdata;
d2d6c096
LP
702 bool ro;
703 int r;
704
705 assert(bus);
706 assert(c);
707 assert(property);
708 assert(reply);
709
5d904a6a 710 ro = strstr(property, "ReadOnly");
d2d6c096
LP
711
712 r = sd_bus_message_open_container(reply, 'a', "(ssbt)");
713 if (r < 0)
714 return r;
715
fe96c0f8 716 for (size_t i = 0; i < c->n_bind_mounts; i++) {
d2d6c096
LP
717
718 if (ro != c->bind_mounts[i].read_only)
719 continue;
720
721 r = sd_bus_message_append(
722 reply, "(ssbt)",
723 c->bind_mounts[i].source,
724 c->bind_mounts[i].destination,
725 c->bind_mounts[i].ignore_enoent,
c9b06108 726 c->bind_mounts[i].recursive ? (uint64_t) MS_REC : (uint64_t) 0);
d2d6c096
LP
727 if (r < 0)
728 return r;
729 }
730
731 return sd_bus_message_close_container(reply);
732}
733
784ad252
YW
734static int property_get_temporary_filesystems(
735 sd_bus *bus,
736 const char *path,
737 const char *interface,
738 const char *property,
739 sd_bus_message *reply,
740 void *userdata,
741 sd_bus_error *error) {
742
743 ExecContext *c = userdata;
784ad252
YW
744 int r;
745
746 assert(bus);
747 assert(c);
748 assert(property);
749 assert(reply);
750
751 r = sd_bus_message_open_container(reply, 'a', "(ss)");
752 if (r < 0)
753 return r;
754
fe96c0f8 755 for (unsigned i = 0; i < c->n_temporary_filesystems; i++) {
784ad252
YW
756 TemporaryFileSystem *t = c->temporary_filesystems + i;
757
758 r = sd_bus_message_append(
759 reply, "(ss)",
760 t->path,
761 t->options);
762 if (r < 0)
763 return r;
764 }
765
766 return sd_bus_message_close_container(reply);
767}
768
d3070fbd
LP
769static int property_get_log_extra_fields(
770 sd_bus *bus,
771 const char *path,
772 const char *interface,
773 const char *property,
774 sd_bus_message *reply,
775 void *userdata,
776 sd_bus_error *error) {
777
778 ExecContext *c = userdata;
d3070fbd
LP
779 int r;
780
781 assert(bus);
782 assert(c);
783 assert(property);
784 assert(reply);
785
786 r = sd_bus_message_open_container(reply, 'a', "ay");
787 if (r < 0)
788 return r;
789
fe96c0f8 790 for (size_t i = 0; i < c->n_log_extra_fields; i++) {
d3070fbd
LP
791 r = sd_bus_message_append_array(reply, 'y', c->log_extra_fields[i].iov_base, c->log_extra_fields[i].iov_len);
792 if (r < 0)
793 return r;
794 }
795
796 return sd_bus_message_close_container(reply);
797}
798
bb0c0d6f
LP
799static int property_get_set_credential(
800 sd_bus *bus,
801 const char *path,
802 const char *interface,
803 const char *property,
804 sd_bus_message *reply,
805 void *userdata,
806 sd_bus_error *error) {
807
808 ExecContext *c = userdata;
809 ExecSetCredential *sc;
bb0c0d6f
LP
810 int r;
811
812 assert(bus);
813 assert(c);
814 assert(property);
815 assert(reply);
816
817 r = sd_bus_message_open_container(reply, 'a', "(say)");
818 if (r < 0)
819 return r;
820
90e74a66 821 HASHMAP_FOREACH(sc, c->set_credentials) {
bb0c0d6f
LP
822
823 r = sd_bus_message_open_container(reply, 'r', "say");
824 if (r < 0)
825 return r;
826
827 r = sd_bus_message_append(reply, "s", sc->id);
828 if (r < 0)
829 return r;
830
831 r = sd_bus_message_append_array(reply, 'y', sc->data, sc->size);
832 if (r < 0)
833 return r;
834
835 r = sd_bus_message_close_container(reply);
836 if (r < 0)
837 return r;
838 }
839
840 return sd_bus_message_close_container(reply);
841}
842
843static int property_get_load_credential(
844 sd_bus *bus,
845 const char *path,
846 const char *interface,
847 const char *property,
848 sd_bus_message *reply,
849 void *userdata,
850 sd_bus_error *error) {
851
852 ExecContext *c = userdata;
853 char **i, **j;
854 int r;
855
856 assert(bus);
857 assert(c);
858 assert(property);
859 assert(reply);
860
861 r = sd_bus_message_open_container(reply, 'a', "(ss)");
862 if (r < 0)
863 return r;
864
865 STRV_FOREACH_PAIR(i, j, c->load_credentials) {
866 r = sd_bus_message_append(reply, "(ss)", *i, *j);
867 if (r < 0)
868 return r;
869 }
870
871 return sd_bus_message_close_container(reply);
872}
873
0389f4fa
LB
874static int property_get_root_hash(
875 sd_bus *bus,
876 const char *path,
877 const char *interface,
878 const char *property,
879 sd_bus_message *reply,
880 void *userdata,
881 sd_bus_error *error) {
882
883 ExecContext *c = userdata;
884
885 assert(bus);
886 assert(c);
887 assert(property);
888 assert(reply);
889
890 return sd_bus_message_append_array(reply, 'y', c->root_hash, c->root_hash_size);
891}
892
d4d55b0d
LB
893static int property_get_root_hash_sig(
894 sd_bus *bus,
895 const char *path,
896 const char *interface,
897 const char *property,
898 sd_bus_message *reply,
899 void *userdata,
900 sd_bus_error *error) {
901
902 ExecContext *c = userdata;
903
904 assert(bus);
905 assert(c);
906 assert(property);
907 assert(reply);
908
909 return sd_bus_message_append_array(reply, 'y', c->root_hash_sig, c->root_hash_sig_size);
910}
911
18d73705
LB
912static int property_get_root_image_options(
913 sd_bus *bus,
914 const char *path,
915 const char *interface,
916 const char *property,
917 sd_bus_message *reply,
918 void *userdata,
919 sd_bus_error *error) {
920
921 ExecContext *c = userdata;
922 MountOptions *m;
923 int r;
924
925 assert(bus);
926 assert(c);
927 assert(property);
928 assert(reply);
929
9ece6444 930 r = sd_bus_message_open_container(reply, 'a', "(ss)");
18d73705
LB
931 if (r < 0)
932 return r;
933
934 LIST_FOREACH(mount_options, m, c->root_image_options) {
9ece6444
LB
935 r = sd_bus_message_append(reply, "(ss)",
936 partition_designator_to_string(m->partition_designator),
937 m->options);
18d73705
LB
938 if (r < 0)
939 return r;
940 }
941
942 return sd_bus_message_close_container(reply);
943}
944
b3d13314
LB
945static int property_get_mount_images(
946 sd_bus *bus,
947 const char *path,
948 const char *interface,
949 const char *property,
950 sd_bus_message *reply,
951 void *userdata,
952 sd_bus_error *error) {
953
954 ExecContext *c = userdata;
955 int r;
956
957 assert(bus);
958 assert(c);
959 assert(property);
960 assert(reply);
961
427353f6 962 r = sd_bus_message_open_container(reply, 'a', "(ssba(ss))");
b3d13314
LB
963 if (r < 0)
964 return r;
965
966 for (size_t i = 0; i < c->n_mount_images; i++) {
427353f6
LB
967 MountOptions *m;
968
969 r = sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "ssba(ss)");
970 if (r < 0)
971 return r;
b3d13314 972 r = sd_bus_message_append(
427353f6 973 reply, "ssb",
b3d13314
LB
974 c->mount_images[i].source,
975 c->mount_images[i].destination,
976 c->mount_images[i].ignore_enoent);
977 if (r < 0)
978 return r;
427353f6
LB
979 r = sd_bus_message_open_container(reply, 'a', "(ss)");
980 if (r < 0)
981 return r;
982 LIST_FOREACH(mount_options, m, c->mount_images[i].mount_options) {
983 r = sd_bus_message_append(reply, "(ss)",
984 partition_designator_to_string(m->partition_designator),
985 m->options);
986 if (r < 0)
987 return r;
988 }
989 r = sd_bus_message_close_container(reply);
990 if (r < 0)
991 return r;
992 r = sd_bus_message_close_container(reply);
993 if (r < 0)
994 return r;
b3d13314
LB
995 }
996
997 return sd_bus_message_close_container(reply);
998}
999
93f59701
LB
1000static int property_get_extension_images(
1001 sd_bus *bus,
1002 const char *path,
1003 const char *interface,
1004 const char *property,
1005 sd_bus_message *reply,
1006 void *userdata,
1007 sd_bus_error *error) {
1008
1009 ExecContext *c = userdata;
1010 int r;
1011
1012 assert(bus);
1013 assert(c);
1014 assert(property);
1015 assert(reply);
1016
1017 r = sd_bus_message_open_container(reply, 'a', "(sba(ss))");
1018 if (r < 0)
1019 return r;
1020
1021 for (size_t i = 0; i < c->n_extension_images; i++) {
1022 MountOptions *m;
1023
1024 r = sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "sba(ss)");
1025 if (r < 0)
1026 return r;
1027 r = sd_bus_message_append(
1028 reply, "sb",
1029 c->extension_images[i].source,
1030 c->extension_images[i].ignore_enoent);
1031 if (r < 0)
1032 return r;
1033 r = sd_bus_message_open_container(reply, 'a', "(ss)");
1034 if (r < 0)
1035 return r;
1036 LIST_FOREACH(mount_options, m, c->extension_images[i].mount_options) {
1037 r = sd_bus_message_append(reply, "(ss)",
1038 partition_designator_to_string(m->partition_designator),
1039 m->options);
1040 if (r < 0)
1041 return r;
1042 }
1043 r = sd_bus_message_close_container(reply);
1044 if (r < 0)
1045 return r;
1046 r = sd_bus_message_close_container(reply);
1047 if (r < 0)
1048 return r;
1049 }
1050
1051 return sd_bus_message_close_container(reply);
1052}
1053
718db961
LP
1054const sd_bus_vtable bus_exec_vtable[] = {
1055 SD_BUS_VTABLE_START(0),
556089dc
LP
1056 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
1057 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
b4c14404 1058 SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
00819cc1 1059 SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL, offsetof(ExecContext, unset_environment), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 1060 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1061 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1062 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1063 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1064 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1065 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1066 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1067 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1068 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1069 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1070 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1071 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1072 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1073 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1074 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1075 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1076 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1077 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1078 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1079 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1080 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1081 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1082 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1083 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1084 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1085 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1086 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1087 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1088 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1089 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1090 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 1091 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 1092 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
5f5d8eab 1093 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 1094 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
915e6d16 1095 SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
9ece6444 1096 SD_BUS_PROPERTY("RootImageOptions", "a(ss)", property_get_root_image_options, 0, SD_BUS_VTABLE_PROPERTY_CONST),
0389f4fa
LB
1097 SD_BUS_PROPERTY("RootHash", "ay", property_get_root_hash, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1098 SD_BUS_PROPERTY("RootHashPath", "s", NULL, offsetof(ExecContext, root_hash_path), SD_BUS_VTABLE_PROPERTY_CONST),
d4d55b0d
LB
1099 SD_BUS_PROPERTY("RootHashSignature", "ay", property_get_root_hash_sig, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1100 SD_BUS_PROPERTY("RootHashSignaturePath", "s", NULL, offsetof(ExecContext, root_hash_sig_path), SD_BUS_VTABLE_PROPERTY_CONST),
0389f4fa 1101 SD_BUS_PROPERTY("RootVerity", "s", NULL, offsetof(ExecContext, root_verity), SD_BUS_VTABLE_PROPERTY_CONST),
93f59701 1102 SD_BUS_PROPERTY("ExtensionImages", "a(sba(ss))", property_get_extension_images, 0, SD_BUS_VTABLE_PROPERTY_CONST),
427353f6 1103 SD_BUS_PROPERTY("MountImages", "a(ssba(ss))", property_get_mount_images, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 1104 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
ad21e542 1105 SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 1106 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
7f452159
LP
1107 SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1108 SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
1109 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1110 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1111 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
e2b2fb7f 1112 SD_BUS_PROPERTY("CPUAffinityFromNUMA", "b", property_get_cpu_affinity_from_numa, 0, SD_BUS_VTABLE_PROPERTY_CONST),
b070c7c0
MS
1113 SD_BUS_PROPERTY("NUMAPolicy", "i", property_get_numa_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1114 SD_BUS_PROPERTY("NUMAMask", "ay", property_get_numa_mask, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
1115 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1116 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
1117 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
1118 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
5073ff6b 1119 SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
08f3be7a 1120 SD_BUS_PROPERTY("StandardInputData", "ay", property_get_input_data, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 1121 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
5073ff6b 1122 SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 1123 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
5073ff6b 1124 SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
1125 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
1126 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
1127 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
1128 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
1129 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
1130 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
1131 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
9d5527f2
YW
1132 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
1133 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
d3070fbd 1134 SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int, offsetof(ExecContext, log_level_max), SD_BUS_VTABLE_PROPERTY_CONST),
5ac1530e
ZJS
1135 SD_BUS_PROPERTY("LogRateLimitIntervalUSec", "t", bus_property_get_usec, offsetof(ExecContext, log_ratelimit_interval_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1136 SD_BUS_PROPERTY("LogRateLimitBurst", "u", bus_property_get_unsigned, offsetof(ExecContext, log_ratelimit_burst), SD_BUS_VTABLE_PROPERTY_CONST),
d3070fbd 1137 SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields, 0, SD_BUS_VTABLE_PROPERTY_CONST),
91dd5f7c 1138 SD_BUS_PROPERTY("LogNamespace", "s", NULL, offsetof(ExecContext, log_namespace), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 1139 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
c0159e20
YW
1140 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", NULL, offsetof(ExecContext, capability_bounding_set), SD_BUS_VTABLE_PROPERTY_CONST),
1141 SD_BUS_PROPERTY("AmbientCapabilities", "t", NULL, offsetof(ExecContext, capability_ambient_set), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
1142 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
1143 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
29206d46 1144 SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
00d9ef85 1145 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
bb0c0d6f
LP
1146 SD_BUS_PROPERTY("SetCredential", "a(say)", property_get_set_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1147 SD_BUS_PROPERTY("LoadCredential", "a(ss)", property_get_load_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 1148 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 1149 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
2a624c36
AP
1150 SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST),
1151 SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST),
1152 SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
ddc155b2
TM
1153 SD_BUS_PROPERTY("ExecPaths", "as", NULL, offsetof(ExecContext, exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
1154 SD_BUS_PROPERTY("NoExecPaths", "as", NULL, offsetof(ExecContext, no_exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
1155 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
1156 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
7f112f50 1157 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
b8b7b838 1158 SD_BUS_PROPERTY("ProtectClock", "b", bus_property_get_bool, offsetof(ExecContext, protect_clock), SD_BUS_VTABLE_PROPERTY_CONST),
59eeb84b 1159 SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST),
502d704e 1160 SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_modules), SD_BUS_VTABLE_PROPERTY_CONST),
84703040 1161 SD_BUS_PROPERTY("ProtectKernelLogs", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_logs), SD_BUS_VTABLE_PROPERTY_CONST),
59eeb84b 1162 SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST),
d251207d
LP
1163 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
1164 SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
228af36f 1165 SD_BUS_PROPERTY("PrivateMounts", "b", bus_property_get_bool, offsetof(ExecContext, private_mounts), SD_BUS_VTABLE_PROPERTY_CONST),
a70581ff 1166 SD_BUS_PROPERTY("PrivateIPC", "b", bus_property_get_bool, offsetof(ExecContext, private_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
73b84e92
YW
1167 SD_BUS_PROPERTY("ProtectHome", "s", property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
1168 SD_BUS_PROPERTY("ProtectSystem", "s", property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
1169 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
1170 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
023a4f67 1171 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
5f8640fb 1172 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
eef65bf3 1173 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2ca620c4 1174 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
1175 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
1176 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
57183d11
LP
1177 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1178 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
cf9d43a8 1179 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST),
9df2cdd8 1180 SD_BUS_PROPERTY("SystemCallLog", "(bas)", property_get_syscall_log, 0, SD_BUS_VTABLE_PROPERTY_CONST),
491eecb3 1181 SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST),
78e864e5 1182 SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
4298d0b5 1183 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
53f47dfc 1184 SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
3536f49e
YW
1185 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1186 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].paths), SD_BUS_VTABLE_PROPERTY_CONST),
e940c1ef
YW
1187 SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1188 SD_BUS_PROPERTY("StateDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
3536f49e
YW
1189 SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1190 SD_BUS_PROPERTY("CacheDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
1191 SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1192 SD_BUS_PROPERTY("LogsDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].paths), SD_BUS_VTABLE_PROPERTY_CONST),
1193 SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST),
1194 SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST),
12213aed 1195 SD_BUS_PROPERTY("TimeoutCleanUSec", "t", bus_property_get_usec, offsetof(ExecContext, timeout_clean_usec), SD_BUS_VTABLE_PROPERTY_CONST),
f3e43635 1196 SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
f4170c67 1197 SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
f69567cb 1198 SD_BUS_PROPERTY("RestrictSUIDSGID", "b", bus_property_get_bool, offsetof(ExecContext, restrict_suid_sgid), SD_BUS_VTABLE_PROPERTY_CONST),
6a8c2d59 1199 SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
d2d6c096
LP
1200 SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1201 SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
784ad252 1202 SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems, 0, SD_BUS_VTABLE_PROPERTY_CONST),
5e98086d 1203 SD_BUS_PROPERTY("MountAPIVFS", "b", property_get_mount_apivfs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
b1edf445 1204 SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST),
4e399953
LP
1205 SD_BUS_PROPERTY("ProtectProc", "s", property_get_protect_proc, offsetof(ExecContext, protect_proc), SD_BUS_VTABLE_PROPERTY_CONST),
1206 SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset, offsetof(ExecContext, proc_subset), SD_BUS_VTABLE_PROPERTY_CONST),
aecd5ac6 1207 SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
a8d08f39 1208 SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
a70581ff 1209 SD_BUS_PROPERTY("IPCNamespacePath", "s", NULL, offsetof(ExecContext, ipc_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
7f452159
LP
1210
1211 /* Obsolete/redundant properties: */
1212 SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1213 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1214 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1215 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1216 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1217
718db961
LP
1218 SD_BUS_VTABLE_END
1219};
82c121a4 1220
4d4c80d0
LP
1221static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
1222 int r;
1223
1224 assert(reply);
1225 assert(c);
1226
1227 if (!c->path)
1228 return 0;
1229
1230 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
1231 if (r < 0)
1232 return r;
1233
1234 r = sd_bus_message_append(reply, "s", c->path);
1235 if (r < 0)
1236 return r;
1237
1238 r = sd_bus_message_append_strv(reply, c->argv);
1239 if (r < 0)
1240 return r;
1241
1242 r = sd_bus_message_append(reply, "bttttuii",
3ed0cd26 1243 !!(c->flags & EXEC_COMMAND_IGNORE_FAILURE),
4d4c80d0
LP
1244 c->exec_status.start_timestamp.realtime,
1245 c->exec_status.start_timestamp.monotonic,
1246 c->exec_status.exit_timestamp.realtime,
1247 c->exec_status.exit_timestamp.monotonic,
1248 (uint32_t) c->exec_status.pid,
1249 (int32_t) c->exec_status.code,
1250 (int32_t) c->exec_status.status);
1251 if (r < 0)
1252 return r;
1253
1254 return sd_bus_message_close_container(reply);
1255}
1256
b3d59367
AZ
1257static int append_exec_ex_command(sd_bus_message *reply, ExecCommand *c) {
1258 _cleanup_strv_free_ char **ex_opts = NULL;
1259 int r;
1260
1261 assert(reply);
1262 assert(c);
1263
1264 if (!c->path)
1265 return 0;
1266
1267 r = sd_bus_message_open_container(reply, 'r', "sasasttttuii");
1268 if (r < 0)
1269 return r;
1270
1271 r = sd_bus_message_append(reply, "s", c->path);
1272 if (r < 0)
1273 return r;
1274
1275 r = sd_bus_message_append_strv(reply, c->argv);
1276 if (r < 0)
1277 return r;
1278
1279 r = exec_command_flags_to_strv(c->flags, &ex_opts);
1280 if (r < 0)
1281 return r;
1282
1283 r = sd_bus_message_append_strv(reply, ex_opts);
1284 if (r < 0)
1285 return r;
1286
1287 r = sd_bus_message_append(reply, "ttttuii",
1288 c->exec_status.start_timestamp.realtime,
1289 c->exec_status.start_timestamp.monotonic,
1290 c->exec_status.exit_timestamp.realtime,
1291 c->exec_status.exit_timestamp.monotonic,
1292 (uint32_t) c->exec_status.pid,
1293 (int32_t) c->exec_status.code,
1294 (int32_t) c->exec_status.status);
1295 if (r < 0)
1296 return r;
1297
1298 return sd_bus_message_close_container(reply);
1299}
1300
718db961
LP
1301int bus_property_get_exec_command(
1302 sd_bus *bus,
1303 const char *path,
1304 const char *interface,
1305 const char *property,
1306 sd_bus_message *reply,
ebcf1f97
LP
1307 void *userdata,
1308 sd_bus_error *ret_error) {
fe68089d 1309
4d4c80d0 1310 ExecCommand *c = (ExecCommand*) userdata;
718db961 1311 int r;
fe68089d 1312
718db961
LP
1313 assert(bus);
1314 assert(reply);
fe68089d 1315
718db961
LP
1316 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
1317 if (r < 0)
1318 return r;
fe68089d 1319
4d4c80d0
LP
1320 r = append_exec_command(reply, c);
1321 if (r < 0)
1322 return r;
fe68089d 1323
4d4c80d0
LP
1324 return sd_bus_message_close_container(reply);
1325}
718db961 1326
4d4c80d0
LP
1327int bus_property_get_exec_command_list(
1328 sd_bus *bus,
1329 const char *path,
1330 const char *interface,
1331 const char *property,
1332 sd_bus_message *reply,
1333 void *userdata,
1334 sd_bus_error *ret_error) {
718db961 1335
4d4c80d0
LP
1336 ExecCommand *c = *(ExecCommand**) userdata;
1337 int r;
718db961 1338
4d4c80d0
LP
1339 assert(bus);
1340 assert(reply);
1341
1342 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
1343 if (r < 0)
1344 return r;
718db961 1345
4d4c80d0
LP
1346 LIST_FOREACH(command, c, c) {
1347 r = append_exec_command(reply, c);
718db961
LP
1348 if (r < 0)
1349 return r;
fe68089d
LP
1350 }
1351
718db961 1352 return sd_bus_message_close_container(reply);
8351ceae 1353}
c7040b5d 1354
b3d59367
AZ
1355int bus_property_get_exec_ex_command_list(
1356 sd_bus *bus,
1357 const char *path,
1358 const char *interface,
1359 const char *property,
1360 sd_bus_message *reply,
1361 void *userdata,
1362 sd_bus_error *ret_error) {
1363
1364 ExecCommand *c, *exec_command = *(ExecCommand**) userdata;
1365 int r;
1366
1367 assert(bus);
1368 assert(reply);
1369
1370 r = sd_bus_message_open_container(reply, 'a', "(sasasttttuii)");
1371 if (r < 0)
1372 return r;
1373
1374 LIST_FOREACH(command, c, exec_command) {
1375 r = append_exec_ex_command(reply, c);
1376 if (r < 0)
1377 return r;
1378 }
1379
1380 return sd_bus_message_close_container(reply);
1381}
1382
1383static char *exec_command_flags_to_exec_chars(ExecCommandFlags flags) {
a4fc96c8
ZJS
1384 return strjoin(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE) ? "-" : "",
1385 FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND) ? ":" : "",
1386 FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) ? "+" : "",
1387 FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "",
1388 FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC) ? "!!" : "");
b3d59367
AZ
1389}
1390
237f7bcb 1391int bus_set_transient_exec_command(
9c0320e7
YW
1392 Unit *u,
1393 const char *name,
1394 ExecCommand **exec_command,
1395 sd_bus_message *message,
1396 UnitWriteFlags flags,
1397 sd_bus_error *error) {
b3d59367 1398 bool is_ex_prop = endswith(name, "Ex");
9c0320e7
YW
1399 unsigned n = 0;
1400 int r;
1401
b3d59367 1402 r = sd_bus_message_enter_container(message, 'a', is_ex_prop ? "(sasas)" : "(sasb)");
9c0320e7
YW
1403 if (r < 0)
1404 return r;
1405
b3d59367
AZ
1406 while ((r = sd_bus_message_enter_container(message, 'r', is_ex_prop ? "sasas" : "sasb")) > 0) {
1407 _cleanup_strv_free_ char **argv = NULL, **ex_opts = NULL;
9c0320e7
YW
1408 const char *path;
1409 int b;
1410
1411 r = sd_bus_message_read(message, "s", &path);
1412 if (r < 0)
1413 return r;
1414
8038b99d
ZJS
1415 if (!path_is_absolute(path) && !filename_is_valid(path))
1416 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
1417 "\"%s\" is neither a valid executable name nor an absolute path",
1418 path);
9c0320e7
YW
1419
1420 r = sd_bus_message_read_strv(message, &argv);
1421 if (r < 0)
1422 return r;
1423
b3d59367 1424 r = is_ex_prop ? sd_bus_message_read_strv(message, &ex_opts) : sd_bus_message_read(message, "b", &b);
9c0320e7
YW
1425 if (r < 0)
1426 return r;
1427
1428 r = sd_bus_message_exit_container(message);
1429 if (r < 0)
1430 return r;
1431
1432 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1433 ExecCommand *c;
1434
1435 c = new0(ExecCommand, 1);
1436 if (!c)
1437 return -ENOMEM;
1438
1439 c->path = strdup(path);
1440 if (!c->path) {
1441 free(c);
1442 return -ENOMEM;
1443 }
1444
ae2a15bc 1445 c->argv = TAKE_PTR(argv);
9c0320e7 1446
b3d59367
AZ
1447 if (is_ex_prop) {
1448 r = exec_command_flags_from_strv(ex_opts, &c->flags);
1449 if (r < 0)
1450 return r;
1451 } else
1452 c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
9c0320e7 1453
858d36c1 1454 path_simplify(c->path, false);
9c0320e7
YW
1455 exec_command_append_list(exec_command, c);
1456 }
1457
1458 n++;
1459 }
1460 if (r < 0)
1461 return r;
1462
1463 r = sd_bus_message_exit_container(message);
1464 if (r < 0)
1465 return r;
1466
1467 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1468 _cleanup_free_ char *buf = NULL;
1469 _cleanup_fclose_ FILE *f = NULL;
1470 ExecCommand *c;
1471 size_t size = 0;
1472
1473 if (n == 0)
1474 *exec_command = exec_command_free_list(*exec_command);
1475
2fe21124 1476 f = open_memstream_unlocked(&buf, &size);
9c0320e7
YW
1477 if (!f)
1478 return -ENOMEM;
1479
f14bf013 1480 fprintf(f, "%s=\n", name);
9c0320e7
YW
1481
1482 LIST_FOREACH(command, c, *exec_command) {
540ac933 1483 _cleanup_free_ char *a = NULL, *exec_chars = NULL;
9c0320e7 1484
540ac933
LP
1485 exec_chars = exec_command_flags_to_exec_chars(c->flags);
1486 if (!exec_chars)
9c0320e7
YW
1487 return -ENOMEM;
1488
1489 a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
1490 if (!a)
1491 return -ENOMEM;
1492
540ac933
LP
1493 if (streq_ptr(c->path, c->argv ? c->argv[0] : NULL))
1494 fprintf(f, "%s=%s%s\n", name, exec_chars, a);
1495 else {
1496 _cleanup_free_ char *t = NULL;
1497 const char *p;
1498
1499 p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
1500 if (!p)
1501 return -ENOMEM;
b3d59367 1502
540ac933
LP
1503 fprintf(f, "%s=%s@%s %s\n", name, exec_chars, p, a);
1504 }
9c0320e7
YW
1505 }
1506
1507 r = fflush_and_check(f);
1508 if (r < 0)
1509 return r;
1510
1511 unit_write_setting(u, flags, name, buf);
1512 }
1513
1514 return 1;
1515}
1516
7e2a3fcc
YW
1517static int parse_personality(const char *s, unsigned long *p) {
1518 unsigned long v;
1519
1520 assert(p);
1521
1522 v = personality_from_string(s);
1523 if (v == PERSONALITY_INVALID)
1524 return -EINVAL;
1525
1526 *p = v;
1527 return 0;
1528}
1529
1530static const char* mount_propagation_flags_to_string_with_check(unsigned long n) {
1531 if (!IN_SET(n, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
1532 return NULL;
1533
1534 return mount_propagation_flags_to_string(n);
1535}
1536
1537static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT);
1538static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid);
aad67b80 1539#if HAVE_SECCOMP
005bfaf1 1540static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, seccomp_errno_or_action_is_valid);
aad67b80 1541#endif
7e2a3fcc
YW
1542static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string);
1543static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string);
1544static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_from_string);
1e8c7bd5
YW
1545static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, protect_system_from_string);
1546static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, protect_home_from_string);
7e2a3fcc 1547static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string);
4e399953
LP
1548static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_proc, ProtectProc, protect_proc_from_string);
1549static BUS_DEFINE_SET_TRANSIENT_PARSE(proc_subset, ProcSubset, proc_subset_from_string);
7e2a3fcc
YW
1550static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string);
1551static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality);
1552static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check);
1553static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint64_t, "%" PRIu64, capability_set_to_string_alloc);
86c2a9f1 1554static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flags_to_string);
7e2a3fcc
YW
1555static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check);
1556
c7040b5d
LP
1557int bus_exec_context_set_transient_property(
1558 Unit *u,
1559 ExecContext *c,
1560 const char *name,
1561 sd_bus_message *message,
2e59b241 1562 UnitWriteFlags flags,
c7040b5d
LP
1563 sd_bus_error *error) {
1564
6550c24c
LP
1565 const char *suffix;
1566 int r;
c7040b5d
LP
1567
1568 assert(u);
1569 assert(c);
1570 assert(name);
1571 assert(message);
1572
2e59b241
LP
1573 flags |= UNIT_PRIVATE;
1574
7e2a3fcc 1575 if (streq(name, "User"))
7a8867ab 1576 return bus_set_transient_user_relaxed(u, name, &c->user, message, flags, error);
c7040b5d 1577
7e2a3fcc 1578 if (streq(name, "Group"))
7a8867ab 1579 return bus_set_transient_user_relaxed(u, name, &c->group, message, flags, error);
c7040b5d 1580
7e2a3fcc
YW
1581 if (streq(name, "TTYPath"))
1582 return bus_set_transient_path(u, name, &c->tty_path, message, flags, error);
6f3e7985 1583
7e2a3fcc
YW
1584 if (streq(name, "RootImage"))
1585 return bus_set_transient_path(u, name, &c->root_image, message, flags, error);
76736280 1586
18d73705
LB
1587 if (streq(name, "RootImageOptions")) {
1588 _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
1589 _cleanup_free_ char *format_str = NULL;
18d73705 1590
988172ce 1591 r = bus_read_mount_options(message, error, &options, &format_str, " ");
18d73705
LB
1592 if (r < 0)
1593 return r;
1594
1595 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1596 if (LIST_IS_EMPTY(options)) {
1597 c->root_image_options = mount_options_free_all(c->root_image_options);
1598 unit_write_settingf(u, flags, name, "%s=", name);
1599 } else {
1600 LIST_JOIN(mount_options, c->root_image_options, options);
1601 unit_write_settingf(
1602 u, flags|UNIT_ESCAPE_SPECIFIERS, name,
1603 "%s=%s",
1604 name,
1605 format_str);
1606 }
1607 }
1608
1609 return 1;
1610 }
1611
0389f4fa
LB
1612 if (streq(name, "RootHash")) {
1613 const void *roothash_decoded;
1614 size_t roothash_decoded_size;
1615
1616 r = sd_bus_message_read_array(message, 'y', &roothash_decoded, &roothash_decoded_size);
1617 if (r < 0)
1618 return r;
1619
1620 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1621 _cleanup_free_ char *encoded = NULL;
1622
1623 if (roothash_decoded_size == 0) {
1624 c->root_hash_path = mfree(c->root_hash_path);
1625 c->root_hash = mfree(c->root_hash);
1626 c->root_hash_size = 0;
1627
1628 unit_write_settingf(u, flags, name, "RootHash=");
1629 } else {
1630 _cleanup_free_ void *p;
1631
1632 encoded = hexmem(roothash_decoded, roothash_decoded_size);
1633 if (!encoded)
1634 return -ENOMEM;
1635
1636 p = memdup(roothash_decoded, roothash_decoded_size);
1637 if (!p)
1638 return -ENOMEM;
1639
1640 free_and_replace(c->root_hash, p);
1641 c->root_hash_size = roothash_decoded_size;
1642 c->root_hash_path = mfree(c->root_hash_path);
1643
1644 unit_write_settingf(u, flags, name, "RootHash=%s", encoded);
1645 }
1646 }
1647
1648 return 1;
1649 }
1650
1651 if (streq(name, "RootHashPath")) {
1652 c->root_hash_size = 0;
1653 c->root_hash = mfree(c->root_hash);
1654
1655 return bus_set_transient_path(u, "RootHash", &c->root_hash_path, message, flags, error);
1656 }
1657
d4d55b0d
LB
1658 if (streq(name, "RootHashSignature")) {
1659 const void *roothash_sig_decoded;
1660 size_t roothash_sig_decoded_size;
1661
1662 r = sd_bus_message_read_array(message, 'y', &roothash_sig_decoded, &roothash_sig_decoded_size);
1663 if (r < 0)
1664 return r;
1665
1666 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1667 _cleanup_free_ char *encoded = NULL;
1668
1669 if (roothash_sig_decoded_size == 0) {
1670 c->root_hash_sig_path = mfree(c->root_hash_sig_path);
1671 c->root_hash_sig = mfree(c->root_hash_sig);
1672 c->root_hash_sig_size = 0;
1673
1674 unit_write_settingf(u, flags, name, "RootHashSignature=");
1675 } else {
1676 _cleanup_free_ void *p;
1677 ssize_t len;
1678
1679 len = base64mem(roothash_sig_decoded, roothash_sig_decoded_size, &encoded);
1680 if (len < 0)
1681 return -ENOMEM;
1682
1683 p = memdup(roothash_sig_decoded, roothash_sig_decoded_size);
1684 if (!p)
1685 return -ENOMEM;
1686
1687 free_and_replace(c->root_hash_sig, p);
1688 c->root_hash_sig_size = roothash_sig_decoded_size;
1689 c->root_hash_sig_path = mfree(c->root_hash_sig_path);
1690
1691 unit_write_settingf(u, flags, name, "RootHashSignature=base64:%s", encoded);
1692 }
1693 }
1694
1695 return 1;
1696 }
1697
1698 if (streq(name, "RootHashSignaturePath")) {
1699 c->root_hash_sig_size = 0;
1700 c->root_hash_sig = mfree(c->root_hash_sig);
1701
1702 return bus_set_transient_path(u, "RootHashSignature", &c->root_hash_sig_path, message, flags, error);
1703 }
1704
0389f4fa
LB
1705 if (streq(name, "RootVerity"))
1706 return bus_set_transient_path(u, name, &c->root_verity, message, flags, error);
1707
7e2a3fcc
YW
1708 if (streq(name, "RootDirectory"))
1709 return bus_set_transient_path(u, name, &c->root_directory, message, flags, error);
c7040b5d 1710
7e2a3fcc
YW
1711 if (streq(name, "SyslogIdentifier"))
1712 return bus_set_transient_string(u, name, &c->syslog_identifier, message, flags, error);
c7040b5d 1713
7e2a3fcc
YW
1714 if (streq(name, "LogLevelMax"))
1715 return bus_set_transient_log_level(u, name, &c->log_level_max, message, flags, error);
1716
90fc172e 1717 if (streq(name, "LogRateLimitIntervalUSec"))
5ac1530e 1718 return bus_set_transient_usec(u, name, &c->log_ratelimit_interval_usec, message, flags, error);
90fc172e
AZ
1719
1720 if (streq(name, "LogRateLimitBurst"))
5ac1530e 1721 return bus_set_transient_unsigned(u, name, &c->log_ratelimit_burst, message, flags, error);
90fc172e 1722
7e2a3fcc
YW
1723 if (streq(name, "Personality"))
1724 return bus_set_transient_personality(u, name, &c->personality, message, flags, error);
1725
7e2a3fcc
YW
1726 if (streq(name, "StandardInput"))
1727 return bus_set_transient_std_input(u, name, &c->std_input, message, flags, error);
1728
1729 if (streq(name, "StandardOutput"))
1730 return bus_set_transient_std_output(u, name, &c->std_output, message, flags, error);
1731
1732 if (streq(name, "StandardError"))
1733 return bus_set_transient_std_output(u, name, &c->std_error, message, flags, error);
1734
1735 if (streq(name, "IgnoreSIGPIPE"))
1736 return bus_set_transient_bool(u, name, &c->ignore_sigpipe, message, flags, error);
1737
1738 if (streq(name, "TTYVHangup"))
1739 return bus_set_transient_bool(u, name, &c->tty_vhangup, message, flags, error);
1740
1741 if (streq(name, "TTYReset"))
1742 return bus_set_transient_bool(u, name, &c->tty_reset, message, flags, error);
1743
1744 if (streq(name, "TTYVTDisallocate"))
1745 return bus_set_transient_bool(u, name, &c->tty_vt_disallocate, message, flags, error);
1746
1747 if (streq(name, "PrivateTmp"))
1748 return bus_set_transient_bool(u, name, &c->private_tmp, message, flags, error);
1749
1750 if (streq(name, "PrivateDevices"))
1751 return bus_set_transient_bool(u, name, &c->private_devices, message, flags, error);
1752
228af36f
LP
1753 if (streq(name, "PrivateMounts"))
1754 return bus_set_transient_bool(u, name, &c->private_mounts, message, flags, error);
1755
7e2a3fcc
YW
1756 if (streq(name, "PrivateNetwork"))
1757 return bus_set_transient_bool(u, name, &c->private_network, message, flags, error);
1758
a70581ff
XR
1759 if (streq(name, "PrivateIPC"))
1760 return bus_set_transient_bool(u, name, &c->private_ipc, message, flags, error);
1761
7e2a3fcc
YW
1762 if (streq(name, "PrivateUsers"))
1763 return bus_set_transient_bool(u, name, &c->private_users, message, flags, error);
1764
1765 if (streq(name, "NoNewPrivileges"))
1766 return bus_set_transient_bool(u, name, &c->no_new_privileges, message, flags, error);
1767
1768 if (streq(name, "SyslogLevelPrefix"))
1769 return bus_set_transient_bool(u, name, &c->syslog_level_prefix, message, flags, error);
1770
1771 if (streq(name, "MemoryDenyWriteExecute"))
1772 return bus_set_transient_bool(u, name, &c->memory_deny_write_execute, message, flags, error);
1773
1774 if (streq(name, "RestrictRealtime"))
1775 return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error);
1776
f69567cb
LP
1777 if (streq(name, "RestrictSUIDSGID"))
1778 return bus_set_transient_bool(u, name, &c->restrict_suid_sgid, message, flags, error);
1779
7e2a3fcc
YW
1780 if (streq(name, "DynamicUser"))
1781 return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error);
1782
1783 if (streq(name, "RemoveIPC"))
1784 return bus_set_transient_bool(u, name, &c->remove_ipc, message, flags, error);
1785
1786 if (streq(name, "ProtectKernelTunables"))
1787 return bus_set_transient_bool(u, name, &c->protect_kernel_tunables, message, flags, error);
1788
1789 if (streq(name, "ProtectKernelModules"))
1790 return bus_set_transient_bool(u, name, &c->protect_kernel_modules, message, flags, error);
1791
84703040
KK
1792 if (streq(name, "ProtectKernelLogs"))
1793 return bus_set_transient_bool(u, name, &c->protect_kernel_logs, message, flags, error);
1794
fc64760d
KK
1795 if (streq(name, "ProtectClock"))
1796 return bus_set_transient_bool(u, name, &c->protect_clock, message, flags, error);
1797
7e2a3fcc
YW
1798 if (streq(name, "ProtectControlGroups"))
1799 return bus_set_transient_bool(u, name, &c->protect_control_groups, message, flags, error);
1800
7e2a3fcc
YW
1801 if (streq(name, "CPUSchedulingResetOnFork"))
1802 return bus_set_transient_bool(u, name, &c->cpu_sched_reset_on_fork, message, flags, error);
1803
1804 if (streq(name, "NonBlocking"))
1805 return bus_set_transient_bool(u, name, &c->non_blocking, message, flags, error);
1806
1807 if (streq(name, "LockPersonality"))
1808 return bus_set_transient_bool(u, name, &c->lock_personality, message, flags, error);
1809
aecd5ac6
TM
1810 if (streq(name, "ProtectHostname"))
1811 return bus_set_transient_bool(u, name, &c->protect_hostname, message, flags, error);
1812
7e2a3fcc
YW
1813 if (streq(name, "UtmpIdentifier"))
1814 return bus_set_transient_string(u, name, &c->utmp_id, message, flags, error);
1815
1816 if (streq(name, "UtmpMode"))
1817 return bus_set_transient_utmp_mode(u, name, &c->utmp_mode, message, flags, error);
1818
1819 if (streq(name, "PAMName"))
1820 return bus_set_transient_string(u, name, &c->pam_name, message, flags, error);
1821
1822 if (streq(name, "TimerSlackNSec"))
1823 return bus_set_transient_nsec(u, name, &c->timer_slack_nsec, message, flags, error);
1824
1825 if (streq(name, "ProtectSystem"))
1826 return bus_set_transient_protect_system(u, name, &c->protect_system, message, flags, error);
1827
1828 if (streq(name, "ProtectHome"))
1829 return bus_set_transient_protect_home(u, name, &c->protect_home, message, flags, error);
cffaed83 1830
7e2a3fcc
YW
1831 if (streq(name, "KeyringMode"))
1832 return bus_set_transient_keyring_mode(u, name, &c->keyring_mode, message, flags, error);
1833
4e399953
LP
1834 if (streq(name, "ProtectProc"))
1835 return bus_set_transient_protect_proc(u, name, &c->protect_proc, message, flags, error);
1836
1837 if (streq(name, "ProcSubset"))
1838 return bus_set_transient_proc_subset(u, name, &c->proc_subset, message, flags, error);
1839
7e2a3fcc
YW
1840 if (streq(name, "RuntimeDirectoryPreserve"))
1841 return bus_set_transient_preserve_mode(u, name, &c->runtime_directory_preserve_mode, message, flags, error);
1842
1843 if (streq(name, "UMask"))
1844 return bus_set_transient_mode_t(u, name, &c->umask, message, flags, error);
1845
1846 if (streq(name, "RuntimeDirectoryMode"))
1847 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_RUNTIME].mode, message, flags, error);
1848
1849 if (streq(name, "StateDirectoryMode"))
1850 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_STATE].mode, message, flags, error);
1851
1852 if (streq(name, "CacheDirectoryMode"))
1853 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CACHE].mode, message, flags, error);
1854
1855 if (streq(name, "LogsDirectoryMode"))
1856 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_LOGS].mode, message, flags, error);
1857
1858 if (streq(name, "ConfigurationDirectoryMode"))
1859 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CONFIGURATION].mode, message, flags, error);
1860
1861 if (streq(name, "SELinuxContext"))
1862 return bus_set_transient_string(u, name, &c->selinux_context, message, flags, error);
1863
1864 if (streq(name, "SecureBits"))
1865 return bus_set_transient_secure_bits(u, name, &c->secure_bits, message, flags, error);
1866
1867 if (streq(name, "CapabilityBoundingSet"))
1868 return bus_set_transient_capability(u, name, &c->capability_bounding_set, message, flags, error);
1869
1870 if (streq(name, "AmbientCapabilities"))
1871 return bus_set_transient_capability(u, name, &c->capability_ambient_set, message, flags, error);
1872
7e2a3fcc
YW
1873 if (streq(name, "RestrictNamespaces"))
1874 return bus_set_transient_namespace_flag(u, name, &c->restrict_namespaces, message, flags, error);
1875
1876 if (streq(name, "MountFlags"))
1877 return bus_set_transient_mount_flags(u, name, &c->mount_flags, message, flags, error);
1878
a8d08f39
LP
1879 if (streq(name, "NetworkNamespacePath"))
1880 return bus_set_transient_path(u, name, &c->network_namespace_path, message, flags, error);
1881
a70581ff
XR
1882 if (streq(name, "IPCNamespacePath"))
1883 return bus_set_transient_path(u, name, &c->ipc_namespace_path, message, flags, error);
1884
7e2a3fcc 1885 if (streq(name, "SupplementaryGroups")) {
cffaed83
YW
1886 _cleanup_strv_free_ char **l = NULL;
1887 char **p;
1888
1889 r = sd_bus_message_read_strv(message, &l);
1890 if (r < 0)
1891 return r;
1892
d2a23692 1893 STRV_FOREACH(p, l)
7a8867ab 1894 if (!isempty(*p) && !valid_user_group_name(*p, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN))
d2a23692
ZJS
1895 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
1896 "Invalid supplementary group names");
cffaed83 1897
2e59b241 1898 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7b943bb7 1899 if (strv_isempty(l)) {
cffaed83 1900 c->supplementary_groups = strv_free(c->supplementary_groups);
2e59b241 1901 unit_write_settingf(u, flags, name, "%s=", name);
cffaed83
YW
1902 } else {
1903 _cleanup_free_ char *joined = NULL;
1904
1905 r = strv_extend_strv(&c->supplementary_groups, l, true);
1906 if (r < 0)
1907 return -ENOMEM;
1908
1909 joined = strv_join(c->supplementary_groups, " ");
1910 if (!joined)
1911 return -ENOMEM;
1912
2e59b241 1913 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, joined);
cffaed83
YW
1914 }
1915 }
1916
1917 return 1;
1918
bb0c0d6f
LP
1919 } else if (streq(name, "SetCredential")) {
1920 bool isempty = true;
1921
1922 r = sd_bus_message_enter_container(message, 'a', "(say)");
1923 if (r < 0)
1924 return r;
1925
1926 for (;;) {
1927 const char *id;
1928 const void *p;
1929 size_t sz;
1930
1931 r = sd_bus_message_enter_container(message, 'r', "say");
1932 if (r < 0)
1933 return r;
1934 if (r == 0)
1935 break;
1936
1937 r = sd_bus_message_read(message, "s", &id);
1938 if (r < 0)
1939 return r;
1940
1941 r = sd_bus_message_read_array(message, 'y', &p, &sz);
1942 if (r < 0)
1943 return r;
1944
1945 r = sd_bus_message_exit_container(message);
1946 if (r < 0)
1947 return r;
1948
1949 if (!credential_name_valid(id))
1950 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Credential ID is invalid: %s", id);
1951
1952 isempty = false;
1953
1954 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1955 _cleanup_free_ char *a = NULL, *b = NULL;
1956 _cleanup_free_ void *copy = NULL;
1957 ExecSetCredential *old;
1958
1959 copy = memdup(p, sz);
1960 if (!copy)
1961 return -ENOMEM;
1962
1963 old = hashmap_get(c->set_credentials, id);
1964 if (old) {
1965 free_and_replace(old->data, copy);
1966 old->size = sz;
1967 } else {
1968 _cleanup_(exec_set_credential_freep) ExecSetCredential *sc = NULL;
1969
1970 sc = new0(ExecSetCredential, 1);
1971 if (!sc)
1972 return -ENOMEM;
1973
1974 sc->id = strdup(id);
1975 if (!sc->id)
1976 return -ENOMEM;
1977
1978 sc->data = TAKE_PTR(copy);
1979 sc->size = sz;
1980
cf55fe4a 1981 r = hashmap_ensure_put(&c->set_credentials, &exec_set_credential_hash_ops, sc->id, sc);
bb0c0d6f
LP
1982 if (r < 0)
1983 return r;
1984
1985 TAKE_PTR(sc);
1986 }
1987
1988 a = specifier_escape(id);
1989 if (!a)
1990 return -ENOMEM;
1991
1992 b = cescape_length(p, sz);
1993 if (!b)
1994 return -ENOMEM;
1995
1996 (void) unit_write_settingf(u, flags, name, "%s=%s:%s", name, a, b);
1997 }
1998 }
1999
2000 r = sd_bus_message_exit_container(message);
2001 if (r < 0)
2002 return r;
2003
2004 if (!UNIT_WRITE_FLAGS_NOOP(flags) && isempty) {
2005 c->set_credentials = hashmap_free(c->set_credentials);
2006 (void) unit_write_settingf(u, flags, name, "%s=", name);
2007 }
2008
2009 return 1;
2010
2011 } else if (streq(name, "LoadCredential")) {
2012 bool isempty = true;
2013
2014 r = sd_bus_message_enter_container(message, 'a', "(ss)");
2015 if (r < 0)
2016 return r;
2017
2018 for (;;) {
2019 const char *id, *source;
2020
2021 r = sd_bus_message_read(message, "(ss)", &id, &source);
2022 if (r < 0)
2023 return r;
2024 if (r == 0)
2025 break;
2026
2027 if (!credential_name_valid(id))
2028 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Credential ID is invalid: %s", id);
2029
2030 if (!(path_is_absolute(source) ? path_is_normalized(source) : credential_name_valid(source)))
2031 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Credential source is invalid: %s", source);
2032
2033 isempty = false;
2034
2035 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2036 r = strv_extend_strv(&c->load_credentials, STRV_MAKE(id, source), /* filter_duplicates = */ false);
2037 if (r < 0)
2038 return r;
2039
2040 (void) unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s:%s", name, id, source);
2041 }
2042 }
2043
2044 r = sd_bus_message_exit_container(message);
2045 if (r < 0)
2046 return r;
2047
2048 if (!UNIT_WRITE_FLAGS_NOOP(flags) && isempty) {
2049 c->load_credentials = strv_free(c->load_credentials);
2050 (void) unit_write_settingf(u, flags, name, "%s=", name);
2051 }
2052
2053 return 1;
2054
a8a13575 2055 } else if (streq(name, "SyslogLevel")) {
8d1dd6ab 2056 int32_t level;
a8a13575
EV
2057
2058 r = sd_bus_message_read(message, "i", &level);
2059 if (r < 0)
2060 return r;
2061
e0d6e0fa
EV
2062 if (!log_level_is_valid(level))
2063 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
2064
2e59b241 2065 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
a8a13575 2066 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
2e59b241 2067 unit_write_settingf(u, flags, name, "SyslogLevel=%i", level);
a8a13575
EV
2068 }
2069
460ed929 2070 return 1;
7e2a3fcc 2071
460ed929 2072 } else if (streq(name, "SyslogFacility")) {
8d1dd6ab 2073 int32_t facility;
460ed929
EV
2074
2075 r = sd_bus_message_read(message, "i", &facility);
2076 if (r < 0)
2077 return r;
2078
e0d6e0fa
EV
2079 if (!log_facility_unshifted_is_valid(facility))
2080 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
2081
2e59b241 2082 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
460ed929 2083 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
2e59b241 2084 unit_write_settingf(u, flags, name, "SyslogFacility=%i", facility);
460ed929
EV
2085 }
2086
cffaed83 2087 return 1;
d3070fbd 2088
91dd5f7c
LP
2089 } else if (streq(name, "LogNamespace")) {
2090 const char *n;
2091
2092 r = sd_bus_message_read(message, "s", &n);
2093 if (r < 0)
2094 return r;
2095
2096 if (!isempty(n) && !log_namespace_name_valid(n))
2097 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log namespace name not valid");
2098
2099 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2100
2101 if (isempty(n)) {
2102 c->log_namespace = mfree(c->log_namespace);
2103 unit_write_settingf(u, flags, name, "%s=", name);
2104 } else {
2105 r = free_and_strdup(&c->log_namespace, n);
2106 if (r < 0)
2107 return r;
2108
2109 unit_write_settingf(u, flags, name, "%s=%s", name, n);
2110 }
2111 }
2112
2113 return 1;
2114
d3070fbd
LP
2115 } else if (streq(name, "LogExtraFields")) {
2116 size_t n = 0;
2117
2118 r = sd_bus_message_enter_container(message, 'a', "ay");
2119 if (r < 0)
2120 return r;
2121
2122 for (;;) {
2123 _cleanup_free_ void *copy = NULL;
2124 struct iovec *t;
2125 const char *eq;
2126 const void *p;
2127 size_t sz;
2128
2129 /* Note that we expect a byte array for each field, instead of a string. That's because on the
2130 * lower-level journal fields can actually contain binary data and are not restricted to text,
2131 * and we should not "lose precision" in our types on the way. That said, I am pretty sure
2132 * actually encoding binary data as unit metadata is not a good idea. Hence we actually refuse
2133 * any actual binary data, and only accept UTF-8. This allows us to eventually lift this
2134 * limitation, should a good, valid usecase arise. */
2135
2136 r = sd_bus_message_read_array(message, 'y', &p, &sz);
2137 if (r < 0)
2138 return r;
2139 if (r == 0)
2140 break;
2141
2142 if (memchr(p, 0, sz))
2143 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains zero byte");
2144
2145 eq = memchr(p, '=', sz);
2146 if (!eq)
2147 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains no '=' character");
2148 if (!journal_field_valid(p, eq - (const char*) p, false))
2149 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field invalid");
2150
2e59b241 2151 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
aa484f35 2152 t = reallocarray(c->log_extra_fields, c->n_log_extra_fields+1, sizeof(struct iovec));
d3070fbd
LP
2153 if (!t)
2154 return -ENOMEM;
2155 c->log_extra_fields = t;
2156 }
2157
2158 copy = malloc(sz + 1);
2159 if (!copy)
2160 return -ENOMEM;
2161
2162 memcpy(copy, p, sz);
2163 ((uint8_t*) copy)[sz] = 0;
2164
2165 if (!utf8_is_valid(copy))
2166 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field is not valid UTF-8");
2167
2e59b241 2168 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
d3070fbd 2169 c->log_extra_fields[c->n_log_extra_fields++] = IOVEC_MAKE(copy, sz);
2e59b241 2170 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C, name, "LogExtraFields=%s", (char*) copy);
d3070fbd
LP
2171
2172 copy = NULL;
2173 }
2174
2175 n++;
2176 }
2177
2178 r = sd_bus_message_exit_container(message);
2179 if (r < 0)
2180 return r;
2181
2e59b241 2182 if (!UNIT_WRITE_FLAGS_NOOP(flags) && n == 0) {
d3070fbd 2183 exec_context_free_log_extra_fields(c);
2e59b241 2184 unit_write_setting(u, flags, name, "LogExtraFields=");
d3070fbd
LP
2185 }
2186
2187 return 1;
7e2a3fcc 2188 }
cffaed83 2189
349cc4a5 2190#if HAVE_SECCOMP
cffaed83 2191
7e2a3fcc
YW
2192 if (streq(name, "SystemCallErrorNumber"))
2193 return bus_set_transient_errno(u, name, &c->syscall_errno, message, flags, error);
2194
2195 if (streq(name, "SystemCallFilter")) {
6b000af4 2196 int allow_list;
3f856a28 2197 _cleanup_strv_free_ char **l = NULL;
cffaed83
YW
2198
2199 r = sd_bus_message_enter_container(message, 'r', "bas");
2200 if (r < 0)
2201 return r;
2202
6b000af4 2203 r = sd_bus_message_read(message, "b", &allow_list);
cffaed83
YW
2204 if (r < 0)
2205 return r;
2206
2207 r = sd_bus_message_read_strv(message, &l);
2208 if (r < 0)
2209 return r;
2210
2211 r = sd_bus_message_exit_container(message);
2212 if (r < 0)
2213 return r;
2214
2e59b241 2215 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83 2216 _cleanup_free_ char *joined = NULL;
6b000af4 2217 SeccompParseFlags invert_flag = allow_list ? 0 : SECCOMP_PARSE_INVERT;
898748d8 2218 char **s;
cffaed83 2219
7b943bb7 2220 if (strv_isempty(l)) {
6b000af4 2221 c->syscall_allow_list = false;
8cfa775f 2222 c->syscall_filter = hashmap_free(c->syscall_filter);
cffaed83 2223
898748d8
YW
2224 unit_write_settingf(u, flags, name, "SystemCallFilter=");
2225 return 1;
2226 }
cffaed83 2227
898748d8
YW
2228 if (!c->syscall_filter) {
2229 c->syscall_filter = hashmap_new(NULL);
2230 if (!c->syscall_filter)
2231 return log_oom();
cffaed83 2232
6b000af4 2233 c->syscall_allow_list = allow_list;
8cfa775f 2234
6b000af4 2235 if (c->syscall_allow_list) {
e7ccdfa8
ZJS
2236 r = seccomp_parse_syscall_filter("@default",
2237 -1,
2238 c->syscall_filter,
72545ae0 2239 SECCOMP_PARSE_PERMISSIVE |
6b000af4 2240 SECCOMP_PARSE_ALLOW_LIST | invert_flag,
58f6ab44
ZJS
2241 u->id,
2242 NULL, 0);
8cfa775f
YW
2243 if (r < 0)
2244 return r;
898748d8
YW
2245 }
2246 }
8cfa775f 2247
898748d8
YW
2248 STRV_FOREACH(s, l) {
2249 _cleanup_free_ char *n = NULL;
2250 int e;
cffaed83 2251
898748d8
YW
2252 r = parse_syscall_and_errno(*s, &n, &e);
2253 if (r < 0)
2254 return r;
cffaed83 2255
084a46d7
YW
2256 if (allow_list && e >= 0)
2257 return -EINVAL;
2258
e7ccdfa8
ZJS
2259 r = seccomp_parse_syscall_filter(n,
2260 e,
2261 c->syscall_filter,
72545ae0
AZ
2262 SECCOMP_PARSE_LOG | SECCOMP_PARSE_PERMISSIVE |
2263 invert_flag |
6b000af4 2264 (c->syscall_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0),
58f6ab44
ZJS
2265 u->id,
2266 NULL, 0);
898748d8
YW
2267 if (r < 0)
2268 return r;
cffaed83
YW
2269 }
2270
2271 joined = strv_join(l, " ");
2272 if (!joined)
2273 return -ENOMEM;
2274
6b000af4 2275 unit_write_settingf(u, flags, name, "SystemCallFilter=%s%s", allow_list ? "" : "~", joined);
cffaed83
YW
2276 }
2277
2278 return 1;
2279
9df2cdd8
TM
2280 } else if (streq(name, "SystemCallLog")) {
2281 int allow_list;
2282 _cleanup_strv_free_ char **l = NULL;
2283
2284 r = sd_bus_message_enter_container(message, 'r', "bas");
2285 if (r < 0)
2286 return r;
2287
2288 r = sd_bus_message_read(message, "b", &allow_list);
2289 if (r < 0)
2290 return r;
2291
2292 r = sd_bus_message_read_strv(message, &l);
2293 if (r < 0)
2294 return r;
2295
2296 r = sd_bus_message_exit_container(message);
2297 if (r < 0)
2298 return r;
2299
2300 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2301 _cleanup_free_ char *joined = NULL;
2302 SeccompParseFlags invert_flag = allow_list ? 0 : SECCOMP_PARSE_INVERT;
2303 char **s;
2304
2305 if (strv_isempty(l)) {
2306 c->syscall_log_allow_list = false;
2307 c->syscall_log = hashmap_free(c->syscall_log);
2308
2309 unit_write_settingf(u, flags, name, "SystemCallLog=");
2310 return 1;
2311 }
2312
2313 if (!c->syscall_log) {
2314 c->syscall_log = hashmap_new(NULL);
2315 if (!c->syscall_log)
2316 return log_oom();
2317
2318 c->syscall_log_allow_list = allow_list;
2319 }
2320
2321 STRV_FOREACH(s, l) {
696a13ba
YW
2322 r = seccomp_parse_syscall_filter(*s,
2323 -1, /* errno not used */
9df2cdd8
TM
2324 c->syscall_log,
2325 SECCOMP_PARSE_LOG | SECCOMP_PARSE_PERMISSIVE |
2326 invert_flag |
2327 (c->syscall_log_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0),
2328 u->id,
2329 NULL, 0);
2330 if (r < 0)
2331 return r;
2332 }
2333
2334 joined = strv_join(l, " ");
2335 if (!joined)
2336 return -ENOMEM;
2337
2338 unit_write_settingf(u, flags, name, "SystemCallLog=%s%s", allow_list ? "" : "~", joined);
2339 }
2340
2341 return 1;
2342
cffaed83
YW
2343 } else if (streq(name, "SystemCallArchitectures")) {
2344 _cleanup_strv_free_ char **l = NULL;
2345
2346 r = sd_bus_message_read_strv(message, &l);
2347 if (r < 0)
2348 return r;
2349
2e59b241 2350 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83
YW
2351 _cleanup_free_ char *joined = NULL;
2352
7b943bb7 2353 if (strv_isempty(l))
cffaed83
YW
2354 c->syscall_archs = set_free(c->syscall_archs);
2355 else {
2356 char **s;
2357
cffaed83
YW
2358 STRV_FOREACH(s, l) {
2359 uint32_t a;
2360
2361 r = seccomp_arch_from_string(*s, &a);
2362 if (r < 0)
2363 return r;
2364
de7fef4b 2365 r = set_ensure_put(&c->syscall_archs, NULL, UINT32_TO_PTR(a + 1));
cffaed83
YW
2366 if (r < 0)
2367 return r;
2368 }
2369
2370 }
2371
2372 joined = strv_join(l, " ");
2373 if (!joined)
2374 return -ENOMEM;
2375
2e59b241 2376 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
cffaed83
YW
2377 }
2378
2379 return 1;
2380
cffaed83 2381 } else if (streq(name, "RestrictAddressFamilies")) {
6b000af4 2382 int allow_list;
3f856a28 2383 _cleanup_strv_free_ char **l = NULL;
cffaed83
YW
2384
2385 r = sd_bus_message_enter_container(message, 'r', "bas");
2386 if (r < 0)
2387 return r;
2388
6b000af4 2389 r = sd_bus_message_read(message, "b", &allow_list);
cffaed83
YW
2390 if (r < 0)
2391 return r;
2392
2393 r = sd_bus_message_read_strv(message, &l);
2394 if (r < 0)
2395 return r;
2396
2397 r = sd_bus_message_exit_container(message);
2398 if (r < 0)
2399 return r;
2400
2e59b241 2401 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83 2402 _cleanup_free_ char *joined = NULL;
9ee896d5 2403 char **s;
cffaed83 2404
7b943bb7 2405 if (strv_isempty(l)) {
6b000af4 2406 c->address_families_allow_list = false;
cffaed83 2407 c->address_families = set_free(c->address_families);
cffaed83 2408
9ee896d5
YW
2409 unit_write_settingf(u, flags, name, "RestrictAddressFamilies=");
2410 return 1;
2411 }
cffaed83 2412
9ee896d5
YW
2413 if (!c->address_families) {
2414 c->address_families = set_new(NULL);
2415 if (!c->address_families)
2416 return log_oom();
cffaed83 2417
6b000af4 2418 c->address_families_allow_list = allow_list;
9ee896d5
YW
2419 }
2420
2421 STRV_FOREACH(s, l) {
2422 int af;
cffaed83 2423
9ee896d5 2424 af = af_from_name(*s);
acf4d158
YW
2425 if (af < 0)
2426 return af;
cffaed83 2427
6b000af4 2428 if (allow_list == c->address_families_allow_list) {
cffaed83
YW
2429 r = set_put(c->address_families, INT_TO_PTR(af));
2430 if (r < 0)
2431 return r;
9ee896d5
YW
2432 } else
2433 (void) set_remove(c->address_families, INT_TO_PTR(af));
cffaed83
YW
2434 }
2435
2436 joined = strv_join(l, " ");
2437 if (!joined)
2438 return -ENOMEM;
2439
6b000af4 2440 unit_write_settingf(u, flags, name, "RestrictAddressFamilies=%s%s", allow_list ? "" : "~", joined);
cffaed83
YW
2441 }
2442
2443 return 1;
7e2a3fcc 2444 }
cffaed83 2445#endif
b070c7c0 2446 if (STR_IN_SET(name, "CPUAffinity", "NUMAMask")) {
cffaed83 2447 const void *a;
bd0abfae 2448 size_t n;
b070c7c0 2449 bool affinity = streq(name, "CPUAffinity");
c367f996 2450 _cleanup_(cpu_set_reset) CPUSet set = {};
cffaed83
YW
2451
2452 r = sd_bus_message_read_array(message, 'y', &a, &n);
2453 if (r < 0)
2454 return r;
2455
c367f996
MS
2456 r = cpu_set_from_dbus(a, n, &set);
2457 if (r < 0)
2458 return r;
2459
2e59b241 2460 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83 2461 if (n == 0) {
b070c7c0 2462 cpu_set_reset(affinity ? &c->cpu_set : &c->numa_policy.nodes);
2e59b241 2463 unit_write_settingf(u, flags, name, "%s=", name);
cffaed83
YW
2464 } else {
2465 _cleanup_free_ char *str = NULL;
cffaed83 2466
0985c7c4 2467 str = cpu_set_to_string(&set);
a832893f
ZJS
2468 if (!str)
2469 return -ENOMEM;
cffaed83 2470
0985c7c4
ZJS
2471 /* We forego any optimizations here, and always create the structure using
2472 * cpu_set_add_all(), because we don't want to care if the existing size we
2473 * got over dbus is appropriate. */
b070c7c0 2474 r = cpu_set_add_all(affinity ? &c->cpu_set : &c->numa_policy.nodes, &set);
0985c7c4
ZJS
2475 if (r < 0)
2476 return r;
501941aa 2477
2e59b241 2478 unit_write_settingf(u, flags, name, "%s=%s", name, str);
cffaed83
YW
2479 }
2480 }
2481
c7040b5d
LP
2482 return 1;
2483
e2b2fb7f
MS
2484 } else if (streq(name, "CPUAffinityFromNUMA")) {
2485 int q;
2486
2487 r = sd_bus_message_read_basic(message, 'b', &q);
2488 if (r < 0)
2489 return r;
2490
2491 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2492 c->cpu_affinity_from_numa = q;
2493 unit_write_settingf(u, flags, name, "%s=%s", "CPUAffinity", "numa");
2494 }
2495
2496 return 1;
2497
b070c7c0
MS
2498 } else if (streq(name, "NUMAPolicy")) {
2499 int32_t type;
2500
2501 r = sd_bus_message_read(message, "i", &type);
2502 if (r < 0)
2503 return r;
2504
2505 if (!mpol_is_valid(type))
2506 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NUMAPolicy value: %i", type);
2507
2508 if (!UNIT_WRITE_FLAGS_NOOP(flags))
2509 c->numa_policy.type = type;
2510
2511 return 1;
e2b2fb7f 2512
c250bf67
YW
2513 } else if (streq(name, "Nice")) {
2514 int32_t q;
2515
2516 r = sd_bus_message_read(message, "i", &q);
2517 if (r < 0)
2518 return r;
2519
2520 if (!nice_is_valid(q))
2521 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Nice value: %i", q);
2522
2523 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2524 c->nice = q;
2525 c->nice_set = true;
2526
2527 unit_write_settingf(u, flags, name, "Nice=%i", q);
2528 }
2529
2530 return 1;
2531
2532 } else if (streq(name, "CPUSchedulingPolicy")) {
2533 int32_t q;
2534
2535 r = sd_bus_message_read(message, "i", &q);
2536 if (r < 0)
2537 return r;
2538
2539 if (!sched_policy_is_valid(q))
2540 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy: %i", q);
2541
2542 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2543 _cleanup_free_ char *s = NULL;
2544
2545 r = sched_policy_to_string_alloc(q, &s);
2546 if (r < 0)
2547 return r;
2548
2549 c->cpu_sched_policy = q;
2550 c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(q), sched_get_priority_max(q));
2551 c->cpu_sched_set = true;
2552
2553 unit_write_settingf(u, flags, name, "CPUSchedulingPolicy=%s", s);
2554 }
2555
2556 return 1;
2557
2558 } else if (streq(name, "CPUSchedulingPriority")) {
2559 int32_t p, min, max;
2560
2561 r = sd_bus_message_read(message, "i", &p);
2562 if (r < 0)
2563 return r;
2564
2565 min = sched_get_priority_min(c->cpu_sched_policy);
2566 max = sched_get_priority_max(c->cpu_sched_policy);
2567 if (p < min || p > max)
2568 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority: %i", p);
2569
2570 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2571 c->cpu_sched_priority = p;
2572 c->cpu_sched_set = true;
2573
2574 unit_write_settingf(u, flags, name, "CPUSchedulingPriority=%i", p);
2575 }
2576
2577 return 1;
2578
7f452159
LP
2579 } else if (streq(name, "IOSchedulingClass")) {
2580 int32_t q;
2581
2582 r = sd_bus_message_read(message, "i", &q);
2583 if (r < 0)
2584 return r;
2585
2586 if (!ioprio_class_is_valid(q))
2587 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q);
2588
2e59b241 2589 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7f452159
LP
2590 _cleanup_free_ char *s = NULL;
2591
2592 r = ioprio_class_to_string_alloc(q, &s);
2593 if (r < 0)
2594 return r;
2595
2596 c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio));
2597 c->ioprio_set = true;
2598
2e59b241 2599 unit_write_settingf(u, flags, name, "IOSchedulingClass=%s", s);
7f452159
LP
2600 }
2601
2602 return 1;
2603
2604 } else if (streq(name, "IOSchedulingPriority")) {
2605 int32_t p;
2606
2607 r = sd_bus_message_read(message, "i", &p);
2608 if (r < 0)
2609 return r;
2610
2611 if (!ioprio_priority_is_valid(p))
2612 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
2613
2e59b241 2614 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7f452159
LP
2615 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p);
2616 c->ioprio_set = true;
2617
2e59b241 2618 unit_write_settingf(u, flags, name, "IOSchedulingPriority=%i", p);
7f452159
LP
2619 }
2620
2621 return 1;
2622
5e98086d
ZJS
2623 } else if (streq(name, "MountAPIVFS")) {
2624 bool b;
2625
2626 r = bus_set_transient_bool(u, name, &b, message, flags, error);
2627 if (r < 0)
2628 return r;
2629
2630 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2631 c->mount_apivfs = b;
2632 c->mount_apivfs_set = true;
2633 }
2634
2635 return 1;
2636
5f5d8eab
LP
2637 } else if (streq(name, "WorkingDirectory")) {
2638 const char *s;
2639 bool missing_ok;
2640
2641 r = sd_bus_message_read(message, "s", &s);
2642 if (r < 0)
2643 return r;
2644
2645 if (s[0] == '-') {
2646 missing_ok = true;
2647 s++;
2648 } else
2649 missing_ok = false;
2650
d6ff82d3 2651 if (!isempty(s) && !streq(s, "~") && !path_is_absolute(s))
5f5d8eab
LP
2652 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
2653
2e59b241 2654 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
5f5d8eab
LP
2655 if (streq(s, "~")) {
2656 c->working_directory = mfree(c->working_directory);
2657 c->working_directory_home = true;
2658 } else {
d6ff82d3 2659 r = free_and_strdup(&c->working_directory, empty_to_null(s));
5f5d8eab
LP
2660 if (r < 0)
2661 return r;
2662
2663 c->working_directory_home = false;
2664 }
2665
2666 c->working_directory_missing_ok = missing_ok;
2e59b241 2667 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
5f5d8eab
LP
2668 }
2669
2670 return 1;
2671
52c239d7
LB
2672 } else if (STR_IN_SET(name,
2673 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
2674 const char *s;
2675
2676 r = sd_bus_message_read(message, "s", &s);
2677 if (r < 0)
2678 return r;
2679
d6ff82d3 2680 if (!isempty(s) && !fdname_is_valid(s))
52c239d7
LB
2681 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
2682
2e59b241 2683 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
5073ff6b 2684
52c239d7 2685 if (streq(name, "StandardInputFileDescriptorName")) {
d6ff82d3 2686 r = free_and_strdup(c->stdio_fdname + STDIN_FILENO, empty_to_null(s));
52c239d7
LB
2687 if (r < 0)
2688 return r;
5073ff6b 2689
0664775c 2690 c->std_input = EXEC_INPUT_NAMED_FD;
2e59b241 2691 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=fd:%s", exec_context_fdname(c, STDIN_FILENO));
5073ff6b 2692
52c239d7 2693 } else if (streq(name, "StandardOutputFileDescriptorName")) {
d6ff82d3 2694 r = free_and_strdup(c->stdio_fdname + STDOUT_FILENO, empty_to_null(s));
52c239d7
LB
2695 if (r < 0)
2696 return r;
5073ff6b 2697
52c239d7 2698 c->std_output = EXEC_OUTPUT_NAMED_FD;
2e59b241 2699 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=fd:%s", exec_context_fdname(c, STDOUT_FILENO));
0664775c
LP
2700
2701 } else {
2702 assert(streq(name, "StandardErrorFileDescriptorName"));
5073ff6b 2703
d6ff82d3 2704 r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], empty_to_null(s));
52c239d7
LB
2705 if (r < 0)
2706 return r;
5073ff6b 2707
52c239d7 2708 c->std_error = EXEC_OUTPUT_NAMED_FD;
2e59b241 2709 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=fd:%s", exec_context_fdname(c, STDERR_FILENO));
52c239d7
LB
2710 }
2711 }
2712
2713 return 1;
2714
566b7d23
ZD
2715 } else if (STR_IN_SET(name,
2716 "StandardInputFile",
8d7dab1f
LW
2717 "StandardOutputFile", "StandardOutputFileToAppend", "StandardOutputFileToTruncate",
2718 "StandardErrorFile", "StandardErrorFileToAppend", "StandardErrorFileToTruncate")) {
2038c3f5
LP
2719 const char *s;
2720
2721 r = sd_bus_message_read(message, "s", &s);
2722 if (r < 0)
2723 return r;
2724
d6ff82d3
YW
2725 if (!isempty(s)) {
2726 if (!path_is_absolute(s))
2727 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute", s);
2728 if (!path_is_normalized(s))
2729 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", s);
2730 }
2038c3f5 2731
2e59b241 2732 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2038c3f5
LP
2733
2734 if (streq(name, "StandardInputFile")) {
d6ff82d3 2735 r = free_and_strdup(&c->stdio_file[STDIN_FILENO], empty_to_null(s));
52c239d7
LB
2736 if (r < 0)
2737 return r;
2038c3f5
LP
2738
2739 c->std_input = EXEC_INPUT_FILE;
2e59b241 2740 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s);
2038c3f5 2741
8d7dab1f 2742 } else if (STR_IN_SET(name, "StandardOutputFile", "StandardOutputFileToAppend", "StandardOutputFileToTruncate")) {
d6ff82d3 2743 r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], empty_to_null(s));
2038c3f5
LP
2744 if (r < 0)
2745 return r;
2746
566b7d23
ZD
2747 if (streq(name, "StandardOutputFile")) {
2748 c->std_output = EXEC_OUTPUT_FILE;
2749 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
8d7dab1f 2750 } else if (streq(name, "StandardOutputFileToAppend")) {
566b7d23
ZD
2751 c->std_output = EXEC_OUTPUT_FILE_APPEND;
2752 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s);
8d7dab1f
LW
2753 } else {
2754 assert(streq(name, "StandardOutputFileToTruncate"));
2755 c->std_output = EXEC_OUTPUT_FILE_TRUNCATE;
2756 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=truncate:%s", s);
566b7d23 2757 }
2038c3f5 2758 } else {
8d7dab1f 2759 assert(STR_IN_SET(name, "StandardErrorFile", "StandardErrorFileToAppend", "StandardErrorFileToTruncate"));
2038c3f5 2760
d6ff82d3 2761 r = free_and_strdup(&c->stdio_file[STDERR_FILENO], empty_to_null(s));
2038c3f5
LP
2762 if (r < 0)
2763 return r;
2764
566b7d23
ZD
2765 if (streq(name, "StandardErrorFile")) {
2766 c->std_error = EXEC_OUTPUT_FILE;
1704fba9 2767 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s);
8d7dab1f 2768 } else if (streq(name, "StandardErrorFileToAppend")) {
dbe6c4b6 2769 c->std_error = EXEC_OUTPUT_FILE_APPEND;
1704fba9 2770 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=append:%s", s);
8d7dab1f
LW
2771 } else {
2772 assert(streq(name, "StandardErrorFileToTruncate"));
2773 c->std_error = EXEC_OUTPUT_FILE_TRUNCATE;
2774 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=truncate:%s", s);
566b7d23 2775 }
2038c3f5
LP
2776 }
2777 }
2778
2779 return 1;
2780
08f3be7a
LP
2781 } else if (streq(name, "StandardInputData")) {
2782 const void *p;
2783 size_t sz;
2784
2785 r = sd_bus_message_read_array(message, 'y', &p, &sz);
2786 if (r < 0)
2787 return r;
2788
2e59b241 2789 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
08f3be7a
LP
2790 _cleanup_free_ char *encoded = NULL;
2791
2792 if (sz == 0) {
2793 c->stdin_data = mfree(c->stdin_data);
2794 c->stdin_data_size = 0;
2795
2e59b241 2796 unit_write_settingf(u, flags, name, "StandardInputData=");
08f3be7a
LP
2797 } else {
2798 void *q;
2799 ssize_t n;
2800
2801 if (c->stdin_data_size + sz < c->stdin_data_size || /* check for overflow */
2802 c->stdin_data_size + sz > EXEC_STDIN_DATA_MAX)
2803 return -E2BIG;
2804
2805 n = base64mem(p, sz, &encoded);
2806 if (n < 0)
2807 return (int) n;
2808
2809 q = realloc(c->stdin_data, c->stdin_data_size + sz);
2810 if (!q)
2811 return -ENOMEM;
2812
2813 memcpy((uint8_t*) q + c->stdin_data_size, p, sz);
2814
2815 c->stdin_data = q;
2816 c->stdin_data_size += sz;
2817
2e59b241 2818 unit_write_settingf(u, flags, name, "StandardInputData=%s", encoded);
52c239d7
LB
2819 }
2820 }
2821
2822 return 1;
2823
c7040b5d
LP
2824 } else if (streq(name, "Environment")) {
2825
6171b822 2826 _cleanup_strv_free_ char **l = NULL;
c7040b5d
LP
2827
2828 r = sd_bus_message_read_strv(message, &l);
2829 if (r < 0)
2830 return r;
2831
6171b822 2832 if (!strv_env_is_valid(l))
1c68232e
LP
2833 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
2834
2e59b241 2835 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7b943bb7 2836 if (strv_isempty(l)) {
e9876fc9 2837 c->environment = strv_free(c->environment);
2e59b241 2838 unit_write_setting(u, flags, name, "Environment=");
e9876fc9 2839 } else {
f900f582
ZJS
2840 _cleanup_free_ char *joined = NULL;
2841 char **e;
2842
2e59b241
LP
2843 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
2844 if (!joined)
2845 return -ENOMEM;
2846
6171b822 2847 e = strv_env_merge(2, c->environment, l);
e9876fc9
EV
2848 if (!e)
2849 return -ENOMEM;
c7040b5d 2850
130d3d22 2851 strv_free_and_replace(c->environment, e);
2e59b241 2852 unit_write_settingf(u, flags, name, "Environment=%s", joined);
e9876fc9 2853 }
c7040b5d
LP
2854 }
2855
d584f638
LP
2856 return 1;
2857
00819cc1
LP
2858 } else if (streq(name, "UnsetEnvironment")) {
2859
6171b822 2860 _cleanup_strv_free_ char **l = NULL;
00819cc1
LP
2861
2862 r = sd_bus_message_read_strv(message, &l);
2863 if (r < 0)
2864 return r;
2865
6171b822 2866 if (!strv_env_name_or_assignment_is_valid(l))
00819cc1
LP
2867 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list.");
2868
2e59b241 2869 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7b943bb7 2870 if (strv_isempty(l)) {
00819cc1 2871 c->unset_environment = strv_free(c->unset_environment);
2e59b241 2872 unit_write_setting(u, flags, name, "UnsetEnvironment=");
00819cc1
LP
2873 } else {
2874 _cleanup_free_ char *joined = NULL;
2875 char **e;
2876
2e59b241
LP
2877 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
2878 if (!joined)
2879 return -ENOMEM;
2880
6171b822 2881 e = strv_env_merge(2, c->unset_environment, l);
00819cc1
LP
2882 if (!e)
2883 return -ENOMEM;
2884
130d3d22 2885 strv_free_and_replace(c->unset_environment, e);
2e59b241 2886 unit_write_settingf(u, flags, name, "UnsetEnvironment=%s", joined);
00819cc1
LP
2887 }
2888 }
2889
2890 return 1;
2891
6b862936
EV
2892 } else if (streq(name, "OOMScoreAdjust")) {
2893 int oa;
2894
2895 r = sd_bus_message_read(message, "i", &oa);
2896 if (r < 0)
2897 return r;
2898
2899 if (!oom_score_adjust_is_valid(oa))
2900 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
2901
2e59b241 2902 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
6b862936
EV
2903 c->oom_score_adjust = oa;
2904 c->oom_score_adjust_set = true;
2e59b241 2905 unit_write_settingf(u, flags, name, "OOMScoreAdjust=%i", oa);
6b862936
EV
2906 }
2907
2908 return 1;
2909
ad21e542
ZJS
2910 } else if (streq(name, "CoredumpFilter")) {
2911 uint64_t f;
2912
2913 r = sd_bus_message_read(message, "t", &f);
2914 if (r < 0)
2915 return r;
2916
2917 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2918 c->coredump_filter = f;
2919 c->coredump_filter_set = true;
2920 unit_write_settingf(u, flags, name, "CoredumpFilter=0x%"PRIx64, f);
2921 }
2922
2923 return 1;
2924
ceb728cf
NC
2925 } else if (streq(name, "EnvironmentFiles")) {
2926
2927 _cleanup_free_ char *joined = NULL;
2928 _cleanup_fclose_ FILE *f = NULL;
9b531f04 2929 _cleanup_strv_free_ char **l = NULL;
ceb728cf 2930 size_t size = 0;
2229f656 2931 char **i;
ceb728cf
NC
2932
2933 r = sd_bus_message_enter_container(message, 'a', "(sb)");
2934 if (r < 0)
2935 return r;
2936
2fe21124 2937 f = open_memstream_unlocked(&joined, &size);
ceb728cf
NC
2938 if (!f)
2939 return -ENOMEM;
2940
2e59b241
LP
2941 fputs("EnvironmentFile=\n", f);
2942
2943 STRV_FOREACH(i, c->environment_files) {
2944 _cleanup_free_ char *q = NULL;
2945
2946 q = specifier_escape(*i);
2947 if (!q)
2948 return -ENOMEM;
2949
2950 fprintf(f, "EnvironmentFile=%s\n", q);
2951 }
ceb728cf
NC
2952
2953 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
2954 const char *path;
2955 int b;
2956
ceb728cf
NC
2957 r = sd_bus_message_read(message, "sb", &path, &b);
2958 if (r < 0)
2959 return r;
2960
2961 r = sd_bus_message_exit_container(message);
2962 if (r < 0)
2963 return r;
2964
d2d6c096
LP
2965 if (!path_is_absolute(path))
2966 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
ceb728cf 2967
2e59b241 2968 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
6abdec98 2969 _cleanup_free_ char *q = NULL, *buf = NULL;
ceb728cf 2970
605405c6 2971 buf = strjoin(b ? "-" : "", path);
2229f656 2972 if (!buf)
ceb728cf
NC
2973 return -ENOMEM;
2974
2e59b241 2975 q = specifier_escape(buf);
6abdec98 2976 if (!q)
2e59b241 2977 return -ENOMEM;
2e59b241
LP
2978
2979 fprintf(f, "EnvironmentFile=%s\n", q);
ceb728cf 2980
6abdec98 2981 r = strv_consume(&l, TAKE_PTR(buf));
ceb728cf
NC
2982 if (r < 0)
2983 return r;
2984 }
2985 }
2986 if (r < 0)
2987 return r;
2988
b0830e21
LP
2989 r = sd_bus_message_exit_container(message);
2990 if (r < 0)
2991 return r;
2992
2229f656
LP
2993 r = fflush_and_check(f);
2994 if (r < 0)
2995 return r;
ceb728cf 2996
2e59b241 2997 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2229f656
LP
2998 if (strv_isempty(l)) {
2999 c->environment_files = strv_free(c->environment_files);
2e59b241 3000 unit_write_setting(u, flags, name, "EnvironmentFile=");
2229f656
LP
3001 } else {
3002 r = strv_extend_strv(&c->environment_files, l, true);
3003 if (r < 0)
3004 return r;
3005
2e59b241 3006 unit_write_setting(u, flags, name, joined);
2229f656
LP
3007 }
3008 }
ceb728cf 3009
ceb728cf
NC
3010 return 1;
3011
b4c14404
FB
3012 } else if (streq(name, "PassEnvironment")) {
3013
6171b822 3014 _cleanup_strv_free_ char **l = NULL;
b4c14404
FB
3015
3016 r = sd_bus_message_read_strv(message, &l);
3017 if (r < 0)
3018 return r;
3019
6171b822 3020 if (!strv_env_name_is_valid(l))
00819cc1 3021 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block.");
b4c14404 3022
2e59b241 3023 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
b4c14404
FB
3024 if (strv_isempty(l)) {
3025 c->pass_environment = strv_free(c->pass_environment);
2e59b241 3026 unit_write_setting(u, flags, name, "PassEnvironment=");
b4c14404
FB
3027 } else {
3028 _cleanup_free_ char *joined = NULL;
3029
9d4f242a
YW
3030 r = strv_extend_strv(&c->pass_environment, l, true);
3031 if (r < 0)
3032 return r;
3033
41de9cc2 3034 /* We write just the new settings out to file, with unresolved specifiers. */
2e59b241 3035 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
b4c14404
FB
3036 if (!joined)
3037 return -ENOMEM;
3038
2e59b241 3039 unit_write_settingf(u, flags, name, "PassEnvironment=%s", joined);
b4c14404
FB
3040 }
3041 }
3042
3043 return 1;
3044
2a624c36 3045 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
ddc155b2 3046 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths", "ExecPaths", "NoExecPaths")) {
08596068
EV
3047 _cleanup_strv_free_ char **l = NULL;
3048 char ***dirs;
3049 char **p;
3050
3051 r = sd_bus_message_read_strv(message, &l);
3052 if (r < 0)
3053 return r;
3054
3055 STRV_FOREACH(p, l) {
e7bcff4e 3056 char *i = *p;
20b7a007
LP
3057 size_t offset;
3058
20b7a007
LP
3059 offset = i[0] == '-';
3060 offset += i[offset] == '+';
3061 if (!path_is_absolute(i + offset))
08596068 3062 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
e7bcff4e 3063
858d36c1 3064 path_simplify(i + offset, false);
08596068
EV
3065 }
3066
2e59b241 3067 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c4b41707
AP
3068 if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths"))
3069 dirs = &c->read_write_paths;
3070 else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
3071 dirs = &c->read_only_paths;
ddc155b2
TM
3072 else if (streq(name, "ExecPaths"))
3073 dirs = &c->exec_paths;
3074 else if (streq(name, "NoExecPaths"))
3075 dirs = &c->no_exec_paths;
c4b41707
AP
3076 else /* "InaccessiblePaths" */
3077 dirs = &c->inaccessible_paths;
08596068 3078
7b943bb7 3079 if (strv_isempty(l)) {
08596068 3080 *dirs = strv_free(*dirs);
2e59b241 3081 unit_write_settingf(u, flags, name, "%s=", name);
08596068 3082 } else {
2e59b241 3083 _cleanup_free_ char *joined = NULL;
08596068 3084
2e59b241 3085 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
08596068
EV
3086 if (!joined)
3087 return -ENOMEM;
3088
2e59b241
LP
3089 r = strv_extend_strv(dirs, l, true);
3090 if (r < 0)
3091 return -ENOMEM;
08596068 3092
2e59b241
LP
3093 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
3094 }
08596068
EV
3095 }
3096
3097 return 1;
3098
3536f49e 3099 } else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
fa21b5e3
EV
3100 _cleanup_strv_free_ char **l = NULL;
3101 char **p;
3102
3103 r = sd_bus_message_read_strv(message, &l);
3104 if (r < 0)
3105 return r;
3106
3107 STRV_FOREACH(p, l) {
8994a117
YW
3108 if (!path_is_normalized(*p))
3109 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not normalized: %s", name, *p);
3110
3111 if (path_is_absolute(*p))
3112 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is absolute: %s", name, *p);
3113
3114 if (path_startswith(*p, "private"))
3115 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path can't be 'private': %s", name, *p);
fa21b5e3
EV
3116 }
3117
2e59b241 3118 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3536f49e 3119 ExecDirectoryType i;
b1ea85dc 3120 ExecDirectory *d;
3536f49e 3121
b1ea85dc
LP
3122 assert_se((i = exec_directory_type_from_string(name)) >= 0);
3123 d = c->directories + i;
fa21b5e3
EV
3124
3125 if (strv_isempty(l)) {
b1ea85dc 3126 d->paths = strv_free(d->paths);
2e59b241 3127 unit_write_settingf(u, flags, name, "%s=", name);
fa21b5e3 3128 } else {
2e59b241
LP
3129 _cleanup_free_ char *joined = NULL;
3130
b1ea85dc 3131 r = strv_extend_strv(&d->paths, l, true);
fa21b5e3 3132 if (r < 0)
c425c7c2 3133 return r;
fa21b5e3 3134
2e59b241 3135 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
fa21b5e3
EV
3136 if (!joined)
3137 return -ENOMEM;
3138
2e59b241 3139 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
fa21b5e3
EV
3140 }
3141 }
3142
3143 return 1;
3144
cffaed83
YW
3145 } else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
3146 int ignore;
3147 const char *s;
3148
280921f2 3149 r = sd_bus_message_read(message, "(bs)", &ignore, &s);
cffaed83
YW
3150 if (r < 0)
3151 return r;
3152
2e59b241 3153 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83
YW
3154 char **p;
3155 bool *b;
3156
3157 if (streq(name, "AppArmorProfile")) {
3158 p = &c->apparmor_profile;
3159 b = &c->apparmor_profile_ignore;
3160 } else { /* "SmackProcessLabel" */
3161 p = &c->smack_process_label;
3162 b = &c->smack_process_label_ignore;
3163 }
3164
3165 if (isempty(s)) {
3166 *p = mfree(*p);
3167 *b = false;
3168 } else {
3169 if (free_and_strdup(p, s) < 0)
3170 return -ENOMEM;
3171 *b = ignore;
3172 }
3173
2e59b241 3174 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
cffaed83
YW
3175 }
3176
3177 return 1;
3178
d2d6c096 3179 } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
ec04aef4 3180 char *source, *destination;
4ff4c98a
YW
3181 int ignore_enoent;
3182 uint64_t mount_flags;
3183 bool empty = true;
d2d6c096
LP
3184
3185 r = sd_bus_message_enter_container(message, 'a', "(ssbt)");
3186 if (r < 0)
3187 return r;
3188
4ff4c98a 3189 while ((r = sd_bus_message_read(message, "(ssbt)", &source, &destination, &ignore_enoent, &mount_flags)) > 0) {
d2d6c096
LP
3190
3191 if (!path_is_absolute(source))
3192 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
3193 if (!path_is_absolute(destination))
91d910e3 3194 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
d2d6c096
LP
3195 if (!IN_SET(mount_flags, 0, MS_REC))
3196 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
3197
2e59b241 3198 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
d2d6c096
LP
3199 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
3200 &(BindMount) {
ec04aef4
TM
3201 .source = source,
3202 .destination = destination,
d2d6c096
LP
3203 .read_only = !!strstr(name, "ReadOnly"),
3204 .recursive = !!(mount_flags & MS_REC),
3205 .ignore_enoent = ignore_enoent,
3206 });
3207 if (r < 0)
3208 return r;
3209
2e59b241
LP
3210 unit_write_settingf(
3211 u, flags|UNIT_ESCAPE_SPECIFIERS, name,
d2d6c096
LP
3212 "%s=%s%s:%s:%s",
3213 name,
3214 ignore_enoent ? "-" : "",
3215 source,
3216 destination,
3217 (mount_flags & MS_REC) ? "rbind" : "norbind");
3218 }
3219
3220 empty = false;
3221 }
3222 if (r < 0)
3223 return r;
3224
3225 r = sd_bus_message_exit_container(message);
3226 if (r < 0)
3227 return r;
3228
3229 if (empty) {
3230 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
3231 c->bind_mounts = NULL;
3232 c->n_bind_mounts = 0;
2e59b241
LP
3233
3234 unit_write_settingf(u, flags, name, "%s=", name);
d2d6c096
LP
3235 }
3236
784ad252
YW
3237 return 1;
3238
3239 } else if (streq(name, "TemporaryFileSystem")) {
3240 const char *path, *options;
3241 bool empty = true;
3242
3243 r = sd_bus_message_enter_container(message, 'a', "(ss)");
3244 if (r < 0)
3245 return r;
3246
3247 while ((r = sd_bus_message_read(message, "(ss)", &path, &options)) > 0) {
3248
3249 if (!path_is_absolute(path))
3250 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Mount point %s is not absolute.", path);
3251
3252 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3253 r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, path, options);
3254 if (r < 0)
3255 return r;
3256
3257 unit_write_settingf(
3258 u, flags|UNIT_ESCAPE_SPECIFIERS, name,
3259 "%s=%s:%s",
3260 name,
3261 path,
3262 options);
3263 }
3264
3265 empty = false;
3266 }
3267 if (r < 0)
3268 return r;
3269
3270 r = sd_bus_message_exit_container(message);
3271 if (r < 0)
3272 return r;
3273
3274 if (empty) {
3275 temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems);
3276 c->temporary_filesystems = NULL;
3277 c->n_temporary_filesystems = 0;
3278
3279 unit_write_settingf(u, flags, name, "%s=", name);
3280 }
3281
83555251 3282 return 1;
d2d6c096 3283
6550c24c
LP
3284 } else if ((suffix = startswith(name, "Limit"))) {
3285 const char *soft = NULL;
3286 int ri;
cab2aca3 3287
6550c24c
LP
3288 ri = rlimit_from_string(suffix);
3289 if (ri < 0) {
3290 soft = endswith(suffix, "Soft");
3291 if (soft) {
3292 const char *n;
cab2aca3 3293
6550c24c
LP
3294 n = strndupa(suffix, soft - suffix);
3295 ri = rlimit_from_string(n);
3296 if (ri >= 0)
3297 name = strjoina("Limit", n);
3298 }
cab2aca3 3299 }
d584f638 3300
6550c24c
LP
3301 if (ri >= 0) {
3302 uint64_t rl;
3303 rlim_t x;
d584f638 3304
6550c24c 3305 r = sd_bus_message_read(message, "t", &rl);
cab2aca3
LP
3306 if (r < 0)
3307 return r;
d584f638 3308
f5fbe71d 3309 if (rl == UINT64_MAX)
6550c24c 3310 x = RLIM_INFINITY;
cab2aca3 3311 else {
6550c24c
LP
3312 x = (rlim_t) rl;
3313
3314 if ((uint64_t) x != rl)
3315 return -ERANGE;
d584f638
LP
3316 }
3317
6550c24c
LP
3318 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3319 _cleanup_free_ char *f = NULL;
3320 struct rlimit nl;
3321
3322 if (c->rlimit[ri]) {
3323 nl = *c->rlimit[ri];
3324
3325 if (soft)
3326 nl.rlim_cur = x;
3327 else
3328 nl.rlim_max = x;
3329 } else
3330 /* When the resource limit is not initialized yet, then assign the value to both fields */
3331 nl = (struct rlimit) {
3332 .rlim_cur = x,
3333 .rlim_max = x,
3334 };
3335
3336 r = rlimit_format(&nl, &f);
3337 if (r < 0)
3338 return r;
3339
3340 if (c->rlimit[ri])
3341 *c->rlimit[ri] = nl;
3342 else {
3343 c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
3344 if (!c->rlimit[ri])
3345 return -ENOMEM;
3346 }
3347
3348 unit_write_settingf(u, flags, name, "%s=%s", name, f);
3349 }
3350
3351 return 1;
d584f638
LP
3352 }
3353
b3d13314
LB
3354 } else if (streq(name, "MountImages")) {
3355 _cleanup_free_ char *format_str = NULL;
3356 MountImage *mount_images = NULL;
3357 size_t n_mount_images = 0;
3358 char *source, *destination;
3359 int permissive;
3360
427353f6 3361 r = sd_bus_message_enter_container(message, 'a', "(ssba(ss))");
b3d13314
LB
3362 if (r < 0)
3363 return r;
3364
427353f6
LB
3365 for (;;) {
3366 _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
3367 _cleanup_free_ char *source_escaped = NULL, *destination_escaped = NULL;
b3d13314
LB
3368 char *tuple;
3369
427353f6
LB
3370 r = sd_bus_message_enter_container(message, 'r', "ssba(ss)");
3371 if (r < 0)
3372 return r;
3373
3374 r = sd_bus_message_read(message, "ssb", &source, &destination, &permissive);
3375 if (r <= 0)
3376 break;
3377
b3d13314
LB
3378 if (!path_is_absolute(source))
3379 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
3380 if (!path_is_normalized(source))
3381 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not normalized.", source);
3382 if (!path_is_absolute(destination))
3383 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
3384 if (!path_is_normalized(destination))
3385 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not normalized.", destination);
3386
427353f6
LB
3387 /* Need to store them in the unit with the escapes, so that they can be parsed again */
3388 source_escaped = shell_escape(source, ":");
3389 if (!source_escaped)
3390 return -ENOMEM;
3391 destination_escaped = shell_escape(destination, ":");
3392 if (!destination_escaped)
3393 return -ENOMEM;
3394
3395 tuple = strjoin(format_str,
3396 format_str ? " " : "",
3397 permissive ? "-" : "",
3398 source_escaped,
3399 ":",
3400 destination_escaped);
b3d13314
LB
3401 if (!tuple)
3402 return -ENOMEM;
3403 free_and_replace(format_str, tuple);
3404
988172ce 3405 r = bus_read_mount_options(message, error, &options, &format_str, ":");
427353f6
LB
3406 if (r < 0)
3407 return r;
3408
3409 r = sd_bus_message_exit_container(message);
3410 if (r < 0)
3411 return r;
3412
b3d13314
LB
3413 r = mount_image_add(&mount_images, &n_mount_images,
3414 &(MountImage) {
3415 .source = source,
3416 .destination = destination,
427353f6 3417 .mount_options = options,
b3d13314 3418 .ignore_enoent = permissive,
93f59701 3419 .type = MOUNT_IMAGE_DISCRETE,
b3d13314
LB
3420 });
3421 if (r < 0)
3422 return r;
3423 }
3424 if (r < 0)
3425 return r;
3426
3427 r = sd_bus_message_exit_container(message);
3428 if (r < 0)
3429 return r;
3430
3431 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3432 if (n_mount_images == 0) {
3433 c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images);
3434
3435 unit_write_settingf(u, flags, name, "%s=", name);
3436 } else {
3437 for (size_t i = 0; i < n_mount_images; ++i) {
3438 r = mount_image_add(&c->mount_images, &c->n_mount_images, &mount_images[i]);
3439 if (r < 0)
3440 return r;
3441 }
3442
3443 unit_write_settingf(u, flags|UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS,
3444 name,
3445 "%s=%s",
3446 name,
3447 format_str);
3448 }
3449 }
3450
3451 mount_images = mount_image_free_many(mount_images, &n_mount_images);
3452
93f59701
LB
3453 return 1;
3454 } else if (streq(name, "ExtensionImages")) {
3455 _cleanup_free_ char *format_str = NULL;
3456 MountImage *extension_images = NULL;
3457 size_t n_extension_images = 0;
3458
3459 r = sd_bus_message_enter_container(message, 'a', "(sba(ss))");
3460 if (r < 0)
3461 return r;
3462
3463 for (;;) {
3464 _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
3465 _cleanup_free_ char *source_escaped = NULL;
3466 char *source, *tuple;
3467 int permissive;
3468
3469 r = sd_bus_message_enter_container(message, 'r', "sba(ss)");
3470 if (r < 0)
3471 return r;
3472
3473 r = sd_bus_message_read(message, "sb", &source, &permissive);
3474 if (r <= 0)
3475 break;
3476
3477 if (!path_is_absolute(source))
3478 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
3479 if (!path_is_normalized(source))
3480 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not normalized.", source);
3481
3482 /* Need to store them in the unit with the escapes, so that they can be parsed again */
3483 source_escaped = shell_escape(source, ":");
3484 if (!source_escaped)
3485 return -ENOMEM;
3486
3487 tuple = strjoin(format_str,
3488 format_str ? " " : "",
3489 permissive ? "-" : "",
3490 source_escaped);
3491 if (!tuple)
3492 return -ENOMEM;
3493 free_and_replace(format_str, tuple);
3494
3495 r = bus_read_mount_options(message, error, &options, &format_str, ":");
3496 if (r < 0)
3497 return r;
3498
3499 r = sd_bus_message_exit_container(message);
3500 if (r < 0)
3501 return r;
3502
3503 r = mount_image_add(&extension_images, &n_extension_images,
3504 &(MountImage) {
3505 .source = source,
3506 .mount_options = options,
3507 .ignore_enoent = permissive,
3508 .type = MOUNT_IMAGE_EXTENSION,
3509 });
3510 if (r < 0)
3511 return r;
3512 }
3513 if (r < 0)
3514 return r;
3515
3516 r = sd_bus_message_exit_container(message);
3517 if (r < 0)
3518 return r;
3519
3520 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3521 if (n_extension_images == 0) {
3522 c->extension_images = mount_image_free_many(c->extension_images, &c->n_extension_images);
3523
3524 unit_write_settingf(u, flags, name, "%s=", name);
3525 } else {
3526 for (size_t i = 0; i < n_extension_images; ++i) {
3527 r = mount_image_add(&c->extension_images, &c->n_extension_images, &extension_images[i]);
3528 if (r < 0)
3529 return r;
3530 }
3531
3532 unit_write_settingf(u, flags|UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS,
3533 name,
3534 "%s=%s",
3535 name,
3536 format_str);
3537 }
3538 }
3539
3540 extension_images = mount_image_free_many(extension_images, &n_extension_images);
3541
b3d13314 3542 return 1;
c7040b5d
LP
3543 }
3544
3545 return 0;
3546}