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