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