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