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