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