]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
core: add new option 'tmpfs' to ProtectHome=
[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
d3070fbd
LP
784static int property_get_log_extra_fields(
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 size_t 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', "ay");
803 if (r < 0)
804 return r;
805
806 for (i = 0; i < c->n_log_extra_fields; i++) {
807 r = sd_bus_message_append_array(reply, 'y', c->log_extra_fields[i].iov_base, c->log_extra_fields[i].iov_len);
808 if (r < 0)
809 return r;
810 }
811
812 return sd_bus_message_close_container(reply);
813}
814
718db961
LP
815const sd_bus_vtable bus_exec_vtable[] = {
816 SD_BUS_VTABLE_START(0),
556089dc
LP
817 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
818 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
b4c14404 819 SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
00819cc1 820 SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL, offsetof(ExecContext, unset_environment), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 821 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 822 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 823 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 824 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 825 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 826 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 827 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 828 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 829 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 830 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 831 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 832 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 833 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 834 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 835 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 836 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 837 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 838 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 839 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 840 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 841 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 842 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 843 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 844 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 845 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 846 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 847 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 848 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 849 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 850 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 851 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 852 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 853 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
5f5d8eab 854 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 855 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
915e6d16 856 SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
857 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
858 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
7f452159
LP
859 SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST),
860 SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
861 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
862 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
863 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
864 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
865 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
866 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
867 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
5073ff6b 868 SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
08f3be7a 869 SD_BUS_PROPERTY("StandardInputData", "ay", property_get_input_data, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 870 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
5073ff6b 871 SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 872 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
5073ff6b 873 SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
874 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
875 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
876 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
877 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
878 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
879 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
880 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
06f2ccf9
EV
881 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
882 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
d3070fbd
LP
883 SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int, offsetof(ExecContext, log_level_max), SD_BUS_VTABLE_PROPERTY_CONST),
884 SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
885 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
886 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
755d4b67 887 SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
888 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
889 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
29206d46 890 SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
00d9ef85 891 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 892 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 893 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
2a624c36
AP
894 SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST),
895 SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST),
896 SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
897 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
898 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
7f112f50 899 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
59eeb84b 900 SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST),
502d704e 901 SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_modules), SD_BUS_VTABLE_PROPERTY_CONST),
59eeb84b 902 SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST),
d251207d
LP
903 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
904 SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
1b8689f9
LP
905 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
906 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
907 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
908 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
023a4f67 909 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
5f8640fb 910 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
eef65bf3 911 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2ca620c4 912 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
913 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
914 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
57183d11
LP
915 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
916 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
17df7223 917 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
ac45f971 918 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
78e864e5 919 SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
4298d0b5 920 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
53f47dfc 921 SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
3536f49e
YW
922 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].mode), SD_BUS_VTABLE_PROPERTY_CONST),
923 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].paths), SD_BUS_VTABLE_PROPERTY_CONST),
e940c1ef
YW
924 SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
925 SD_BUS_PROPERTY("StateDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
3536f49e
YW
926 SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
927 SD_BUS_PROPERTY("CacheDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
928 SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST),
929 SD_BUS_PROPERTY("LogsDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].paths), SD_BUS_VTABLE_PROPERTY_CONST),
930 SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST),
931 SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST),
f3e43635 932 SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
f4170c67 933 SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
6a8c2d59 934 SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
d2d6c096
LP
935 SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
936 SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
5d997827 937 SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST),
b1edf445 938 SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST),
7f452159
LP
939
940 /* Obsolete/redundant properties: */
941 SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
942 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
943 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
944 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
945 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
946
718db961
LP
947 SD_BUS_VTABLE_END
948};
82c121a4 949
4d4c80d0
LP
950static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
951 int r;
952
953 assert(reply);
954 assert(c);
955
956 if (!c->path)
957 return 0;
958
959 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
960 if (r < 0)
961 return r;
962
963 r = sd_bus_message_append(reply, "s", c->path);
964 if (r < 0)
965 return r;
966
967 r = sd_bus_message_append_strv(reply, c->argv);
968 if (r < 0)
969 return r;
970
971 r = sd_bus_message_append(reply, "bttttuii",
3ed0cd26 972 !!(c->flags & EXEC_COMMAND_IGNORE_FAILURE),
4d4c80d0
LP
973 c->exec_status.start_timestamp.realtime,
974 c->exec_status.start_timestamp.monotonic,
975 c->exec_status.exit_timestamp.realtime,
976 c->exec_status.exit_timestamp.monotonic,
977 (uint32_t) c->exec_status.pid,
978 (int32_t) c->exec_status.code,
979 (int32_t) c->exec_status.status);
980 if (r < 0)
981 return r;
982
983 return sd_bus_message_close_container(reply);
984}
985
718db961
LP
986int bus_property_get_exec_command(
987 sd_bus *bus,
988 const char *path,
989 const char *interface,
990 const char *property,
991 sd_bus_message *reply,
ebcf1f97
LP
992 void *userdata,
993 sd_bus_error *ret_error) {
fe68089d 994
4d4c80d0 995 ExecCommand *c = (ExecCommand*) userdata;
718db961 996 int r;
fe68089d 997
718db961
LP
998 assert(bus);
999 assert(reply);
fe68089d 1000
718db961
LP
1001 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
1002 if (r < 0)
1003 return r;
fe68089d 1004
4d4c80d0
LP
1005 r = append_exec_command(reply, c);
1006 if (r < 0)
1007 return r;
fe68089d 1008
4d4c80d0
LP
1009 return sd_bus_message_close_container(reply);
1010}
718db961 1011
4d4c80d0
LP
1012int bus_property_get_exec_command_list(
1013 sd_bus *bus,
1014 const char *path,
1015 const char *interface,
1016 const char *property,
1017 sd_bus_message *reply,
1018 void *userdata,
1019 sd_bus_error *ret_error) {
718db961 1020
4d4c80d0
LP
1021 ExecCommand *c = *(ExecCommand**) userdata;
1022 int r;
718db961 1023
4d4c80d0
LP
1024 assert(bus);
1025 assert(reply);
1026
1027 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
1028 if (r < 0)
1029 return r;
718db961 1030
4d4c80d0
LP
1031 LIST_FOREACH(command, c, c) {
1032 r = append_exec_command(reply, c);
718db961
LP
1033 if (r < 0)
1034 return r;
fe68089d
LP
1035 }
1036
718db961 1037 return sd_bus_message_close_container(reply);
8351ceae 1038}
c7040b5d 1039
237f7bcb 1040int bus_set_transient_exec_command(
9c0320e7
YW
1041 Unit *u,
1042 const char *name,
1043 ExecCommand **exec_command,
1044 sd_bus_message *message,
1045 UnitWriteFlags flags,
1046 sd_bus_error *error) {
1047 unsigned n = 0;
1048 int r;
1049
1050 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
1051 if (r < 0)
1052 return r;
1053
1054 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
1055 _cleanup_strv_free_ char **argv = NULL;
1056 const char *path;
1057 int b;
1058
1059 r = sd_bus_message_read(message, "s", &path);
1060 if (r < 0)
1061 return r;
1062
1063 if (!path_is_absolute(path))
1064 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
1065
1066 r = sd_bus_message_read_strv(message, &argv);
1067 if (r < 0)
1068 return r;
1069
1070 r = sd_bus_message_read(message, "b", &b);
1071 if (r < 0)
1072 return r;
1073
1074 r = sd_bus_message_exit_container(message);
1075 if (r < 0)
1076 return r;
1077
1078 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1079 ExecCommand *c;
1080
1081 c = new0(ExecCommand, 1);
1082 if (!c)
1083 return -ENOMEM;
1084
1085 c->path = strdup(path);
1086 if (!c->path) {
1087 free(c);
1088 return -ENOMEM;
1089 }
1090
1091 c->argv = argv;
1092 argv = NULL;
1093
1094 c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
1095
1096 path_kill_slashes(c->path);
1097 exec_command_append_list(exec_command, c);
1098 }
1099
1100 n++;
1101 }
1102 if (r < 0)
1103 return r;
1104
1105 r = sd_bus_message_exit_container(message);
1106 if (r < 0)
1107 return r;
1108
1109 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1110 _cleanup_free_ char *buf = NULL;
1111 _cleanup_fclose_ FILE *f = NULL;
1112 ExecCommand *c;
1113 size_t size = 0;
1114
1115 if (n == 0)
1116 *exec_command = exec_command_free_list(*exec_command);
1117
1118 f = open_memstream(&buf, &size);
1119 if (!f)
1120 return -ENOMEM;
1121
1122 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1123
1124 fputs("ExecStart=\n", f);
1125
1126 LIST_FOREACH(command, c, *exec_command) {
1127 _cleanup_free_ char *a = NULL, *t = NULL;
1128 const char *p;
1129
1130 p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
1131 if (!p)
1132 return -ENOMEM;
1133
1134 a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
1135 if (!a)
1136 return -ENOMEM;
1137
1138 fprintf(f, "%s=%s@%s %s\n",
1139 name,
1140 c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
1141 p,
1142 a);
1143 }
1144
1145 r = fflush_and_check(f);
1146 if (r < 0)
1147 return r;
1148
1149 unit_write_setting(u, flags, name, buf);
1150 }
1151
1152 return 1;
1153}
1154
7e2a3fcc
YW
1155static int parse_personality(const char *s, unsigned long *p) {
1156 unsigned long v;
1157
1158 assert(p);
1159
1160 v = personality_from_string(s);
1161 if (v == PERSONALITY_INVALID)
1162 return -EINVAL;
1163
1164 *p = v;
1165 return 0;
1166}
1167
1168static const char* mount_propagation_flags_to_string_with_check(unsigned long n) {
1169 if (!IN_SET(n, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
1170 return NULL;
1171
1172 return mount_propagation_flags_to_string(n);
1173}
1174
1175static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT);
1176static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid);
aad67b80 1177#if HAVE_SECCOMP
7e2a3fcc 1178static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, errno_is_valid);
aad67b80 1179#endif
7e2a3fcc
YW
1180static BUS_DEFINE_SET_TRANSIENT_IS_VALID(sched_priority, "i", int32_t, int, "%" PRIi32, sched_priority_is_valid);
1181static BUS_DEFINE_SET_TRANSIENT_IS_VALID(nice, "i", int32_t, int, "%" PRIi32, nice_is_valid);
1182static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string);
1183static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string);
1184static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_from_string);
1185static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, parse_protect_system_or_bool);
1186static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, parse_protect_home_or_bool);
1187static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string);
1188static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string);
1189static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality);
1190static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check);
1191static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint64_t, "%" PRIu64, capability_set_to_string_alloc);
1192static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(sched_policy, "i", int32_t, int, "%" PRIi32, sched_policy_to_string_alloc_with_check);
1193static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flag_to_string_many_with_check);
1194static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check);
1195
c7040b5d
LP
1196int bus_exec_context_set_transient_property(
1197 Unit *u,
1198 ExecContext *c,
1199 const char *name,
1200 sd_bus_message *message,
2e59b241 1201 UnitWriteFlags flags,
c7040b5d
LP
1202 sd_bus_error *error) {
1203
cab2aca3
LP
1204 const char *soft = NULL;
1205 int r, ri;
c7040b5d
LP
1206
1207 assert(u);
1208 assert(c);
1209 assert(name);
1210 assert(message);
1211
2e59b241
LP
1212 flags |= UNIT_PRIVATE;
1213
7e2a3fcc
YW
1214 if (streq(name, "User"))
1215 return bus_set_transient_user(u, name, &c->user, message, flags, error);
c7040b5d 1216
7e2a3fcc
YW
1217 if (streq(name, "Group"))
1218 return bus_set_transient_user(u, name, &c->group, message, flags, error);
c7040b5d 1219
7e2a3fcc
YW
1220 if (streq(name, "TTYPath"))
1221 return bus_set_transient_path(u, name, &c->tty_path, message, flags, error);
6f3e7985 1222
7e2a3fcc
YW
1223 if (streq(name, "RootImage"))
1224 return bus_set_transient_path(u, name, &c->root_image, message, flags, error);
76736280 1225
7e2a3fcc
YW
1226 if (streq(name, "RootDirectory"))
1227 return bus_set_transient_path(u, name, &c->root_directory, message, flags, error);
c7040b5d 1228
7e2a3fcc
YW
1229 if (streq(name, "SyslogIdentifier"))
1230 return bus_set_transient_string(u, name, &c->syslog_identifier, message, flags, error);
c7040b5d 1231
7e2a3fcc
YW
1232 if (streq(name, "LogLevelMax"))
1233 return bus_set_transient_log_level(u, name, &c->log_level_max, message, flags, error);
1234
1235 if (streq(name, "CPUSchedulingPriority"))
1236 return bus_set_transient_sched_priority(u, name, &c->cpu_sched_priority, message, flags, error);
1237
1238 if (streq(name, "Personality"))
1239 return bus_set_transient_personality(u, name, &c->personality, message, flags, error);
1240
1241 if (streq(name, "Nice"))
1242 return bus_set_transient_nice(u, name, &c->nice, message, flags, error);
1243
1244 if (streq(name, "StandardInput"))
1245 return bus_set_transient_std_input(u, name, &c->std_input, message, flags, error);
1246
1247 if (streq(name, "StandardOutput"))
1248 return bus_set_transient_std_output(u, name, &c->std_output, message, flags, error);
1249
1250 if (streq(name, "StandardError"))
1251 return bus_set_transient_std_output(u, name, &c->std_error, message, flags, error);
1252
1253 if (streq(name, "IgnoreSIGPIPE"))
1254 return bus_set_transient_bool(u, name, &c->ignore_sigpipe, message, flags, error);
1255
1256 if (streq(name, "TTYVHangup"))
1257 return bus_set_transient_bool(u, name, &c->tty_vhangup, message, flags, error);
1258
1259 if (streq(name, "TTYReset"))
1260 return bus_set_transient_bool(u, name, &c->tty_reset, message, flags, error);
1261
1262 if (streq(name, "TTYVTDisallocate"))
1263 return bus_set_transient_bool(u, name, &c->tty_vt_disallocate, message, flags, error);
1264
1265 if (streq(name, "PrivateTmp"))
1266 return bus_set_transient_bool(u, name, &c->private_tmp, message, flags, error);
1267
1268 if (streq(name, "PrivateDevices"))
1269 return bus_set_transient_bool(u, name, &c->private_devices, message, flags, error);
1270
1271 if (streq(name, "PrivateNetwork"))
1272 return bus_set_transient_bool(u, name, &c->private_network, message, flags, error);
1273
1274 if (streq(name, "PrivateUsers"))
1275 return bus_set_transient_bool(u, name, &c->private_users, message, flags, error);
1276
1277 if (streq(name, "NoNewPrivileges"))
1278 return bus_set_transient_bool(u, name, &c->no_new_privileges, message, flags, error);
1279
1280 if (streq(name, "SyslogLevelPrefix"))
1281 return bus_set_transient_bool(u, name, &c->syslog_level_prefix, message, flags, error);
1282
1283 if (streq(name, "MemoryDenyWriteExecute"))
1284 return bus_set_transient_bool(u, name, &c->memory_deny_write_execute, message, flags, error);
1285
1286 if (streq(name, "RestrictRealtime"))
1287 return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error);
1288
1289 if (streq(name, "DynamicUser"))
1290 return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error);
1291
1292 if (streq(name, "RemoveIPC"))
1293 return bus_set_transient_bool(u, name, &c->remove_ipc, message, flags, error);
1294
1295 if (streq(name, "ProtectKernelTunables"))
1296 return bus_set_transient_bool(u, name, &c->protect_kernel_tunables, message, flags, error);
1297
1298 if (streq(name, "ProtectKernelModules"))
1299 return bus_set_transient_bool(u, name, &c->protect_kernel_modules, message, flags, error);
1300
1301 if (streq(name, "ProtectControlGroups"))
1302 return bus_set_transient_bool(u, name, &c->protect_control_groups, message, flags, error);
1303
1304 if (streq(name, "MountAPIVFS"))
1305 return bus_set_transient_bool(u, name, &c->mount_apivfs, message, flags, error);
1306
1307 if (streq(name, "CPUSchedulingResetOnFork"))
1308 return bus_set_transient_bool(u, name, &c->cpu_sched_reset_on_fork, message, flags, error);
1309
1310 if (streq(name, "NonBlocking"))
1311 return bus_set_transient_bool(u, name, &c->non_blocking, message, flags, error);
1312
1313 if (streq(name, "LockPersonality"))
1314 return bus_set_transient_bool(u, name, &c->lock_personality, message, flags, error);
1315
1316 if (streq(name, "UtmpIdentifier"))
1317 return bus_set_transient_string(u, name, &c->utmp_id, message, flags, error);
1318
1319 if (streq(name, "UtmpMode"))
1320 return bus_set_transient_utmp_mode(u, name, &c->utmp_mode, message, flags, error);
1321
1322 if (streq(name, "PAMName"))
1323 return bus_set_transient_string(u, name, &c->pam_name, message, flags, error);
1324
1325 if (streq(name, "TimerSlackNSec"))
1326 return bus_set_transient_nsec(u, name, &c->timer_slack_nsec, message, flags, error);
1327
1328 if (streq(name, "ProtectSystem"))
1329 return bus_set_transient_protect_system(u, name, &c->protect_system, message, flags, error);
1330
1331 if (streq(name, "ProtectHome"))
1332 return bus_set_transient_protect_home(u, name, &c->protect_home, message, flags, error);
cffaed83 1333
7e2a3fcc
YW
1334 if (streq(name, "KeyringMode"))
1335 return bus_set_transient_keyring_mode(u, name, &c->keyring_mode, message, flags, error);
1336
1337 if (streq(name, "RuntimeDirectoryPreserve"))
1338 return bus_set_transient_preserve_mode(u, name, &c->runtime_directory_preserve_mode, message, flags, error);
1339
1340 if (streq(name, "UMask"))
1341 return bus_set_transient_mode_t(u, name, &c->umask, message, flags, error);
1342
1343 if (streq(name, "RuntimeDirectoryMode"))
1344 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_RUNTIME].mode, message, flags, error);
1345
1346 if (streq(name, "StateDirectoryMode"))
1347 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_STATE].mode, message, flags, error);
1348
1349 if (streq(name, "CacheDirectoryMode"))
1350 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CACHE].mode, message, flags, error);
1351
1352 if (streq(name, "LogsDirectoryMode"))
1353 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_LOGS].mode, message, flags, error);
1354
1355 if (streq(name, "ConfigurationDirectoryMode"))
1356 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CONFIGURATION].mode, message, flags, error);
1357
1358 if (streq(name, "SELinuxContext"))
1359 return bus_set_transient_string(u, name, &c->selinux_context, message, flags, error);
1360
1361 if (streq(name, "SecureBits"))
1362 return bus_set_transient_secure_bits(u, name, &c->secure_bits, message, flags, error);
1363
1364 if (streq(name, "CapabilityBoundingSet"))
1365 return bus_set_transient_capability(u, name, &c->capability_bounding_set, message, flags, error);
1366
1367 if (streq(name, "AmbientCapabilities"))
1368 return bus_set_transient_capability(u, name, &c->capability_ambient_set, message, flags, error);
1369
1370 if (streq(name, "CPUSchedulingPolicy"))
1371 return bus_set_transient_sched_policy(u, name, &c->cpu_sched_policy, message, flags, error);
1372
1373 if (streq(name, "RestrictNamespaces"))
1374 return bus_set_transient_namespace_flag(u, name, &c->restrict_namespaces, message, flags, error);
1375
1376 if (streq(name, "MountFlags"))
1377 return bus_set_transient_mount_flags(u, name, &c->mount_flags, message, flags, error);
1378
1379 if (streq(name, "SupplementaryGroups")) {
cffaed83
YW
1380 _cleanup_strv_free_ char **l = NULL;
1381 char **p;
1382
1383 r = sd_bus_message_read_strv(message, &l);
1384 if (r < 0)
1385 return r;
1386
1387 STRV_FOREACH(p, l) {
1388 if (!isempty(*p) && !valid_user_group_name_or_id(*p))
1389 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid supplementary group names");
1390 }
1391
2e59b241 1392 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7b943bb7 1393 if (strv_isempty(l)) {
cffaed83 1394 c->supplementary_groups = strv_free(c->supplementary_groups);
2e59b241 1395 unit_write_settingf(u, flags, name, "%s=", name);
cffaed83
YW
1396 } else {
1397 _cleanup_free_ char *joined = NULL;
1398
1399 r = strv_extend_strv(&c->supplementary_groups, l, true);
1400 if (r < 0)
1401 return -ENOMEM;
1402
1403 joined = strv_join(c->supplementary_groups, " ");
1404 if (!joined)
1405 return -ENOMEM;
1406
2e59b241 1407 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, joined);
cffaed83
YW
1408 }
1409 }
1410
1411 return 1;
1412
a8a13575 1413 } else if (streq(name, "SyslogLevel")) {
8d1dd6ab 1414 int32_t level;
a8a13575
EV
1415
1416 r = sd_bus_message_read(message, "i", &level);
1417 if (r < 0)
1418 return r;
1419
e0d6e0fa
EV
1420 if (!log_level_is_valid(level))
1421 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
1422
2e59b241 1423 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
a8a13575 1424 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
2e59b241 1425 unit_write_settingf(u, flags, name, "SyslogLevel=%i", level);
a8a13575
EV
1426 }
1427
460ed929 1428 return 1;
7e2a3fcc 1429
460ed929 1430 } else if (streq(name, "SyslogFacility")) {
8d1dd6ab 1431 int32_t facility;
460ed929
EV
1432
1433 r = sd_bus_message_read(message, "i", &facility);
1434 if (r < 0)
1435 return r;
1436
e0d6e0fa
EV
1437 if (!log_facility_unshifted_is_valid(facility))
1438 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
1439
2e59b241 1440 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
460ed929 1441 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
2e59b241 1442 unit_write_settingf(u, flags, name, "SyslogFacility=%i", facility);
460ed929
EV
1443 }
1444
cffaed83 1445 return 1;
d3070fbd 1446
d3070fbd
LP
1447 } else if (streq(name, "LogExtraFields")) {
1448 size_t n = 0;
1449
1450 r = sd_bus_message_enter_container(message, 'a', "ay");
1451 if (r < 0)
1452 return r;
1453
1454 for (;;) {
1455 _cleanup_free_ void *copy = NULL;
1456 struct iovec *t;
1457 const char *eq;
1458 const void *p;
1459 size_t sz;
1460
1461 /* Note that we expect a byte array for each field, instead of a string. That's because on the
1462 * lower-level journal fields can actually contain binary data and are not restricted to text,
1463 * and we should not "lose precision" in our types on the way. That said, I am pretty sure
1464 * actually encoding binary data as unit metadata is not a good idea. Hence we actually refuse
1465 * any actual binary data, and only accept UTF-8. This allows us to eventually lift this
1466 * limitation, should a good, valid usecase arise. */
1467
1468 r = sd_bus_message_read_array(message, 'y', &p, &sz);
1469 if (r < 0)
1470 return r;
1471 if (r == 0)
1472 break;
1473
1474 if (memchr(p, 0, sz))
1475 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains zero byte");
1476
1477 eq = memchr(p, '=', sz);
1478 if (!eq)
1479 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains no '=' character");
1480 if (!journal_field_valid(p, eq - (const char*) p, false))
1481 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field invalid");
1482
2e59b241 1483 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
d3070fbd
LP
1484 t = realloc_multiply(c->log_extra_fields, sizeof(struct iovec), c->n_log_extra_fields+1);
1485 if (!t)
1486 return -ENOMEM;
1487 c->log_extra_fields = t;
1488 }
1489
1490 copy = malloc(sz + 1);
1491 if (!copy)
1492 return -ENOMEM;
1493
1494 memcpy(copy, p, sz);
1495 ((uint8_t*) copy)[sz] = 0;
1496
1497 if (!utf8_is_valid(copy))
1498 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field is not valid UTF-8");
1499
2e59b241 1500 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
d3070fbd 1501 c->log_extra_fields[c->n_log_extra_fields++] = IOVEC_MAKE(copy, sz);
2e59b241 1502 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C, name, "LogExtraFields=%s", (char*) copy);
d3070fbd
LP
1503
1504 copy = NULL;
1505 }
1506
1507 n++;
1508 }
1509
1510 r = sd_bus_message_exit_container(message);
1511 if (r < 0)
1512 return r;
1513
2e59b241 1514 if (!UNIT_WRITE_FLAGS_NOOP(flags) && n == 0) {
d3070fbd 1515 exec_context_free_log_extra_fields(c);
2e59b241 1516 unit_write_setting(u, flags, name, "LogExtraFields=");
d3070fbd
LP
1517 }
1518
1519 return 1;
7e2a3fcc 1520 }
cffaed83 1521
349cc4a5 1522#if HAVE_SECCOMP
cffaed83 1523
7e2a3fcc
YW
1524 if (streq(name, "SystemCallErrorNumber"))
1525 return bus_set_transient_errno(u, name, &c->syscall_errno, message, flags, error);
1526
1527 if (streq(name, "SystemCallFilter")) {
cffaed83 1528 int whitelist;
3f856a28 1529 _cleanup_strv_free_ char **l = NULL;
cffaed83
YW
1530
1531 r = sd_bus_message_enter_container(message, 'r', "bas");
1532 if (r < 0)
1533 return r;
1534
1535 r = sd_bus_message_read(message, "b", &whitelist);
1536 if (r < 0)
1537 return r;
1538
1539 r = sd_bus_message_read_strv(message, &l);
1540 if (r < 0)
1541 return r;
1542
1543 r = sd_bus_message_exit_container(message);
1544 if (r < 0)
1545 return r;
1546
2e59b241 1547 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83 1548 _cleanup_free_ char *joined = NULL;
898748d8
YW
1549 bool invert = !whitelist;
1550 char **s;
cffaed83 1551
7b943bb7 1552 if (strv_isempty(l)) {
cffaed83 1553 c->syscall_whitelist = false;
8cfa775f 1554 c->syscall_filter = hashmap_free(c->syscall_filter);
cffaed83 1555
898748d8
YW
1556 unit_write_settingf(u, flags, name, "SystemCallFilter=");
1557 return 1;
1558 }
cffaed83 1559
898748d8
YW
1560 if (!c->syscall_filter) {
1561 c->syscall_filter = hashmap_new(NULL);
1562 if (!c->syscall_filter)
1563 return log_oom();
cffaed83 1564
898748d8 1565 c->syscall_whitelist = whitelist;
8cfa775f 1566
898748d8
YW
1567 if (c->syscall_whitelist) {
1568 r = seccomp_parse_syscall_filter(invert, "@default", -1, c->syscall_filter, true);
8cfa775f
YW
1569 if (r < 0)
1570 return r;
898748d8
YW
1571 }
1572 }
8cfa775f 1573
898748d8
YW
1574 STRV_FOREACH(s, l) {
1575 _cleanup_free_ char *n = NULL;
1576 int e;
cffaed83 1577
898748d8
YW
1578 r = parse_syscall_and_errno(*s, &n, &e);
1579 if (r < 0)
1580 return r;
cffaed83 1581
898748d8
YW
1582 r = seccomp_parse_syscall_filter(invert, n, e, c->syscall_filter, c->syscall_whitelist);
1583 if (r < 0)
1584 return r;
cffaed83
YW
1585 }
1586
1587 joined = strv_join(l, " ");
1588 if (!joined)
1589 return -ENOMEM;
1590
2e59b241 1591 unit_write_settingf(u, flags, name, "SystemCallFilter=%s%s", whitelist ? "" : "~", joined);
cffaed83
YW
1592 }
1593
1594 return 1;
1595
1596 } else if (streq(name, "SystemCallArchitectures")) {
1597 _cleanup_strv_free_ char **l = NULL;
1598
1599 r = sd_bus_message_read_strv(message, &l);
1600 if (r < 0)
1601 return r;
1602
2e59b241 1603 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83
YW
1604 _cleanup_free_ char *joined = NULL;
1605
7b943bb7 1606 if (strv_isempty(l))
cffaed83
YW
1607 c->syscall_archs = set_free(c->syscall_archs);
1608 else {
1609 char **s;
1610
1611 r = set_ensure_allocated(&c->syscall_archs, NULL);
1612 if (r < 0)
1613 return r;
1614
1615 STRV_FOREACH(s, l) {
1616 uint32_t a;
1617
1618 r = seccomp_arch_from_string(*s, &a);
1619 if (r < 0)
1620 return r;
1621
1622 r = set_put(c->syscall_archs, UINT32_TO_PTR(a + 1));
1623 if (r < 0)
1624 return r;
1625 }
1626
1627 }
1628
1629 joined = strv_join(l, " ");
1630 if (!joined)
1631 return -ENOMEM;
1632
2e59b241 1633 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
cffaed83
YW
1634 }
1635
1636 return 1;
1637
cffaed83
YW
1638 } else if (streq(name, "RestrictAddressFamilies")) {
1639 int whitelist;
3f856a28 1640 _cleanup_strv_free_ char **l = NULL;
cffaed83
YW
1641
1642 r = sd_bus_message_enter_container(message, 'r', "bas");
1643 if (r < 0)
1644 return r;
1645
1646 r = sd_bus_message_read(message, "b", &whitelist);
1647 if (r < 0)
1648 return r;
1649
1650 r = sd_bus_message_read_strv(message, &l);
1651 if (r < 0)
1652 return r;
1653
1654 r = sd_bus_message_exit_container(message);
1655 if (r < 0)
1656 return r;
1657
2e59b241 1658 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83 1659 _cleanup_free_ char *joined = NULL;
9ee896d5
YW
1660 bool invert = !whitelist;
1661 char **s;
cffaed83 1662
7b943bb7 1663 if (strv_isempty(l)) {
cffaed83
YW
1664 c->address_families_whitelist = false;
1665 c->address_families = set_free(c->address_families);
cffaed83 1666
9ee896d5
YW
1667 unit_write_settingf(u, flags, name, "RestrictAddressFamilies=");
1668 return 1;
1669 }
cffaed83 1670
9ee896d5
YW
1671 if (!c->address_families) {
1672 c->address_families = set_new(NULL);
1673 if (!c->address_families)
1674 return log_oom();
cffaed83 1675
9ee896d5
YW
1676 c->address_families_whitelist = whitelist;
1677 }
1678
1679 STRV_FOREACH(s, l) {
1680 int af;
cffaed83 1681
9ee896d5
YW
1682 af = af_from_name(*s);
1683 if (af <= 0)
1684 return -EINVAL;
cffaed83 1685
9ee896d5 1686 if (!invert == c->address_families_whitelist) {
cffaed83
YW
1687 r = set_put(c->address_families, INT_TO_PTR(af));
1688 if (r < 0)
1689 return r;
9ee896d5
YW
1690 } else
1691 (void) set_remove(c->address_families, INT_TO_PTR(af));
cffaed83
YW
1692 }
1693
1694 joined = strv_join(l, " ");
1695 if (!joined)
1696 return -ENOMEM;
1697
2e59b241 1698 unit_write_settingf(u, flags, name, "RestrictAddressFamilies=%s%s", whitelist ? "" : "~", joined);
cffaed83
YW
1699 }
1700
1701 return 1;
7e2a3fcc 1702 }
cffaed83 1703#endif
7e2a3fcc 1704 if (streq(name, "CPUAffinity")) {
cffaed83
YW
1705 const void *a;
1706 size_t n = 0;
1707
1708 r = sd_bus_message_read_array(message, 'y', &a, &n);
1709 if (r < 0)
1710 return r;
1711
2e59b241 1712 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83 1713 if (n == 0) {
501941aa
YW
1714 c->cpuset = cpu_set_mfree(c->cpuset);
1715 c->cpuset_ncpus = 0;
2e59b241 1716 unit_write_settingf(u, flags, name, "%s=", name);
cffaed83
YW
1717 } else {
1718 _cleanup_free_ char *str = NULL;
501941aa 1719 size_t allocated = 0, len = 0, i, ncpus;
cffaed83 1720
501941aa 1721 ncpus = CPU_SIZE_TO_NUM(n);
cffaed83 1722
501941aa 1723 for (i = 0; i < ncpus; i++) {
cffaed83
YW
1724 _cleanup_free_ char *p = NULL;
1725 size_t add;
1726
501941aa
YW
1727 if (!CPU_ISSET_S(i, n, (cpu_set_t*) a))
1728 continue;
1729
1730 r = asprintf(&p, "%zu", i);
cffaed83
YW
1731 if (r < 0)
1732 return -ENOMEM;
1733
1734 add = strlen(p);
1735
501941aa 1736 if (!GREEDY_REALLOC(str, allocated, len + add + 2))
cffaed83
YW
1737 return -ENOMEM;
1738
1739 strcpy(mempcpy(str + len, p, add), " ");
1740 len += add + 1;
1741 }
1742
1743 if (len != 0)
1744 str[len - 1] = '\0';
1745
501941aa
YW
1746 if (!c->cpuset || c->cpuset_ncpus < ncpus) {
1747 cpu_set_t *cpuset;
1748
1749 cpuset = CPU_ALLOC(ncpus);
1750 if (!cpuset)
1751 return -ENOMEM;
1752
1753 CPU_ZERO_S(n, cpuset);
1754 if (c->cpuset) {
1755 CPU_OR_S(CPU_ALLOC_SIZE(c->cpuset_ncpus), cpuset, c->cpuset, (cpu_set_t*) a);
1756 CPU_FREE(c->cpuset);
1757 } else
1758 CPU_OR_S(n, cpuset, cpuset, (cpu_set_t*) a);
1759
1760 c->cpuset = cpuset;
1761 c->cpuset_ncpus = ncpus;
1762 } else
1763 CPU_OR_S(n, c->cpuset, c->cpuset, (cpu_set_t*) a);
1764
2e59b241 1765 unit_write_settingf(u, flags, name, "%s=%s", name, str);
cffaed83
YW
1766 }
1767 }
1768
c7040b5d
LP
1769 return 1;
1770
7f452159
LP
1771 } else if (streq(name, "IOSchedulingClass")) {
1772 int32_t q;
1773
1774 r = sd_bus_message_read(message, "i", &q);
1775 if (r < 0)
1776 return r;
1777
1778 if (!ioprio_class_is_valid(q))
1779 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q);
1780
2e59b241 1781 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7f452159
LP
1782 _cleanup_free_ char *s = NULL;
1783
1784 r = ioprio_class_to_string_alloc(q, &s);
1785 if (r < 0)
1786 return r;
1787
1788 c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio));
1789 c->ioprio_set = true;
1790
2e59b241 1791 unit_write_settingf(u, flags, name, "IOSchedulingClass=%s", s);
7f452159
LP
1792 }
1793
1794 return 1;
1795
1796 } else if (streq(name, "IOSchedulingPriority")) {
1797 int32_t p;
1798
1799 r = sd_bus_message_read(message, "i", &p);
1800 if (r < 0)
1801 return r;
1802
1803 if (!ioprio_priority_is_valid(p))
1804 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
1805
2e59b241 1806 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7f452159
LP
1807 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p);
1808 c->ioprio_set = true;
1809
2e59b241 1810 unit_write_settingf(u, flags, name, "IOSchedulingPriority=%i", p);
7f452159
LP
1811 }
1812
1813 return 1;
1814
5f5d8eab
LP
1815 } else if (streq(name, "WorkingDirectory")) {
1816 const char *s;
1817 bool missing_ok;
1818
1819 r = sd_bus_message_read(message, "s", &s);
1820 if (r < 0)
1821 return r;
1822
1823 if (s[0] == '-') {
1824 missing_ok = true;
1825 s++;
1826 } else
1827 missing_ok = false;
1828
d6ff82d3 1829 if (!isempty(s) && !streq(s, "~") && !path_is_absolute(s))
5f5d8eab
LP
1830 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
1831
2e59b241 1832 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
5f5d8eab
LP
1833 if (streq(s, "~")) {
1834 c->working_directory = mfree(c->working_directory);
1835 c->working_directory_home = true;
1836 } else {
d6ff82d3 1837 r = free_and_strdup(&c->working_directory, empty_to_null(s));
5f5d8eab
LP
1838 if (r < 0)
1839 return r;
1840
1841 c->working_directory_home = false;
1842 }
1843
1844 c->working_directory_missing_ok = missing_ok;
2e59b241 1845 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
5f5d8eab
LP
1846 }
1847
1848 return 1;
1849
52c239d7
LB
1850 } else if (STR_IN_SET(name,
1851 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
1852 const char *s;
1853
1854 r = sd_bus_message_read(message, "s", &s);
1855 if (r < 0)
1856 return r;
1857
d6ff82d3 1858 if (!isempty(s) && !fdname_is_valid(s))
52c239d7
LB
1859 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
1860
2e59b241 1861 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
5073ff6b 1862
52c239d7 1863 if (streq(name, "StandardInputFileDescriptorName")) {
d6ff82d3 1864 r = free_and_strdup(c->stdio_fdname + STDIN_FILENO, empty_to_null(s));
52c239d7
LB
1865 if (r < 0)
1866 return r;
5073ff6b 1867
0664775c 1868 c->std_input = EXEC_INPUT_NAMED_FD;
2e59b241 1869 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=fd:%s", exec_context_fdname(c, STDIN_FILENO));
5073ff6b 1870
52c239d7 1871 } else if (streq(name, "StandardOutputFileDescriptorName")) {
d6ff82d3 1872 r = free_and_strdup(c->stdio_fdname + STDOUT_FILENO, empty_to_null(s));
52c239d7
LB
1873 if (r < 0)
1874 return r;
5073ff6b 1875
52c239d7 1876 c->std_output = EXEC_OUTPUT_NAMED_FD;
2e59b241 1877 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=fd:%s", exec_context_fdname(c, STDOUT_FILENO));
0664775c
LP
1878
1879 } else {
1880 assert(streq(name, "StandardErrorFileDescriptorName"));
5073ff6b 1881
d6ff82d3 1882 r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], empty_to_null(s));
52c239d7
LB
1883 if (r < 0)
1884 return r;
5073ff6b 1885
52c239d7 1886 c->std_error = EXEC_OUTPUT_NAMED_FD;
2e59b241 1887 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=fd:%s", exec_context_fdname(c, STDERR_FILENO));
52c239d7
LB
1888 }
1889 }
1890
1891 return 1;
1892
2038c3f5
LP
1893 } else if (STR_IN_SET(name, "StandardInputFile", "StandardOutputFile", "StandardErrorFile")) {
1894 const char *s;
1895
1896 r = sd_bus_message_read(message, "s", &s);
1897 if (r < 0)
1898 return r;
1899
d6ff82d3
YW
1900 if (!isempty(s)) {
1901 if (!path_is_absolute(s))
1902 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute", s);
1903 if (!path_is_normalized(s))
1904 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", s);
1905 }
2038c3f5 1906
2e59b241 1907 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2038c3f5
LP
1908
1909 if (streq(name, "StandardInputFile")) {
d6ff82d3 1910 r = free_and_strdup(&c->stdio_file[STDIN_FILENO], empty_to_null(s));
52c239d7
LB
1911 if (r < 0)
1912 return r;
2038c3f5
LP
1913
1914 c->std_input = EXEC_INPUT_FILE;
2e59b241 1915 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s);
2038c3f5
LP
1916
1917 } else if (streq(name, "StandardOutputFile")) {
d6ff82d3 1918 r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], empty_to_null(s));
2038c3f5
LP
1919 if (r < 0)
1920 return r;
1921
1922 c->std_output = EXEC_OUTPUT_FILE;
2e59b241 1923 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
2038c3f5
LP
1924
1925 } else {
1926 assert(streq(name, "StandardErrorFile"));
1927
d6ff82d3 1928 r = free_and_strdup(&c->stdio_file[STDERR_FILENO], empty_to_null(s));
2038c3f5
LP
1929 if (r < 0)
1930 return r;
1931
1932 c->std_error = EXEC_OUTPUT_FILE;
2e59b241 1933 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s);
2038c3f5
LP
1934 }
1935 }
1936
1937 return 1;
1938
08f3be7a
LP
1939 } else if (streq(name, "StandardInputData")) {
1940 const void *p;
1941 size_t sz;
1942
1943 r = sd_bus_message_read_array(message, 'y', &p, &sz);
1944 if (r < 0)
1945 return r;
1946
2e59b241 1947 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
08f3be7a
LP
1948 _cleanup_free_ char *encoded = NULL;
1949
1950 if (sz == 0) {
1951 c->stdin_data = mfree(c->stdin_data);
1952 c->stdin_data_size = 0;
1953
2e59b241 1954 unit_write_settingf(u, flags, name, "StandardInputData=");
08f3be7a
LP
1955 } else {
1956 void *q;
1957 ssize_t n;
1958
1959 if (c->stdin_data_size + sz < c->stdin_data_size || /* check for overflow */
1960 c->stdin_data_size + sz > EXEC_STDIN_DATA_MAX)
1961 return -E2BIG;
1962
1963 n = base64mem(p, sz, &encoded);
1964 if (n < 0)
1965 return (int) n;
1966
1967 q = realloc(c->stdin_data, c->stdin_data_size + sz);
1968 if (!q)
1969 return -ENOMEM;
1970
1971 memcpy((uint8_t*) q + c->stdin_data_size, p, sz);
1972
1973 c->stdin_data = q;
1974 c->stdin_data_size += sz;
1975
2e59b241 1976 unit_write_settingf(u, flags, name, "StandardInputData=%s", encoded);
52c239d7
LB
1977 }
1978 }
1979
1980 return 1;
1981
c7040b5d
LP
1982 } else if (streq(name, "Environment")) {
1983
6171b822 1984 _cleanup_strv_free_ char **l = NULL;
c7040b5d
LP
1985
1986 r = sd_bus_message_read_strv(message, &l);
1987 if (r < 0)
1988 return r;
1989
6171b822 1990 if (!strv_env_is_valid(l))
1c68232e
LP
1991 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1992
2e59b241 1993 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7b943bb7 1994 if (strv_isempty(l)) {
e9876fc9 1995 c->environment = strv_free(c->environment);
2e59b241 1996 unit_write_setting(u, flags, name, "Environment=");
e9876fc9 1997 } else {
f900f582
ZJS
1998 _cleanup_free_ char *joined = NULL;
1999 char **e;
2000
2e59b241
LP
2001 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
2002 if (!joined)
2003 return -ENOMEM;
2004
6171b822 2005 e = strv_env_merge(2, c->environment, l);
e9876fc9
EV
2006 if (!e)
2007 return -ENOMEM;
c7040b5d 2008
e9876fc9
EV
2009 strv_free(c->environment);
2010 c->environment = e;
c7040b5d 2011
2e59b241 2012 unit_write_settingf(u, flags, name, "Environment=%s", joined);
e9876fc9 2013 }
c7040b5d
LP
2014 }
2015
d584f638
LP
2016 return 1;
2017
00819cc1
LP
2018 } else if (streq(name, "UnsetEnvironment")) {
2019
6171b822 2020 _cleanup_strv_free_ char **l = NULL;
00819cc1
LP
2021
2022 r = sd_bus_message_read_strv(message, &l);
2023 if (r < 0)
2024 return r;
2025
6171b822 2026 if (!strv_env_name_or_assignment_is_valid(l))
00819cc1
LP
2027 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list.");
2028
2e59b241 2029 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
7b943bb7 2030 if (strv_isempty(l)) {
00819cc1 2031 c->unset_environment = strv_free(c->unset_environment);
2e59b241 2032 unit_write_setting(u, flags, name, "UnsetEnvironment=");
00819cc1
LP
2033 } else {
2034 _cleanup_free_ char *joined = NULL;
2035 char **e;
2036
2e59b241
LP
2037 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
2038 if (!joined)
2039 return -ENOMEM;
2040
6171b822 2041 e = strv_env_merge(2, c->unset_environment, l);
00819cc1
LP
2042 if (!e)
2043 return -ENOMEM;
2044
2045 strv_free(c->unset_environment);
2046 c->unset_environment = e;
2047
2e59b241 2048 unit_write_settingf(u, flags, name, "UnsetEnvironment=%s", joined);
00819cc1
LP
2049 }
2050 }
2051
2052 return 1;
2053
6b862936
EV
2054 } else if (streq(name, "OOMScoreAdjust")) {
2055 int oa;
2056
2057 r = sd_bus_message_read(message, "i", &oa);
2058 if (r < 0)
2059 return r;
2060
2061 if (!oom_score_adjust_is_valid(oa))
2062 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
2063
2e59b241 2064 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
6b862936
EV
2065 c->oom_score_adjust = oa;
2066 c->oom_score_adjust_set = true;
2e59b241 2067 unit_write_settingf(u, flags, name, "OOMScoreAdjust=%i", oa);
6b862936
EV
2068 }
2069
2070 return 1;
2071
ceb728cf
NC
2072 } else if (streq(name, "EnvironmentFiles")) {
2073
2074 _cleanup_free_ char *joined = NULL;
2075 _cleanup_fclose_ FILE *f = NULL;
9b531f04 2076 _cleanup_strv_free_ char **l = NULL;
ceb728cf 2077 size_t size = 0;
2229f656 2078 char **i;
ceb728cf
NC
2079
2080 r = sd_bus_message_enter_container(message, 'a', "(sb)");
2081 if (r < 0)
2082 return r;
2083
2084 f = open_memstream(&joined, &size);
2085 if (!f)
2086 return -ENOMEM;
2087
0d536673
LP
2088 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
2089
2e59b241
LP
2090 fputs("EnvironmentFile=\n", f);
2091
2092 STRV_FOREACH(i, c->environment_files) {
2093 _cleanup_free_ char *q = NULL;
2094
2095 q = specifier_escape(*i);
2096 if (!q)
2097 return -ENOMEM;
2098
2099 fprintf(f, "EnvironmentFile=%s\n", q);
2100 }
ceb728cf
NC
2101
2102 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
2103 const char *path;
2104 int b;
2105
ceb728cf
NC
2106 r = sd_bus_message_read(message, "sb", &path, &b);
2107 if (r < 0)
2108 return r;
2109
2110 r = sd_bus_message_exit_container(message);
2111 if (r < 0)
2112 return r;
2113
d2d6c096
LP
2114 if (!path_is_absolute(path))
2115 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
ceb728cf 2116
2e59b241
LP
2117 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2118 _cleanup_free_ char *q = NULL;
ae978b9f 2119 char *buf;
ceb728cf 2120
605405c6 2121 buf = strjoin(b ? "-" : "", path);
2229f656 2122 if (!buf)
ceb728cf
NC
2123 return -ENOMEM;
2124
2e59b241
LP
2125 q = specifier_escape(buf);
2126 if (!q) {
2127 free(buf);
2128 return -ENOMEM;
2129 }
2130
2131 fprintf(f, "EnvironmentFile=%s\n", q);
ceb728cf 2132
2229f656 2133 r = strv_consume(&l, buf);
ceb728cf
NC
2134 if (r < 0)
2135 return r;
2136 }
2137 }
2138 if (r < 0)
2139 return r;
2140
b0830e21
LP
2141 r = sd_bus_message_exit_container(message);
2142 if (r < 0)
2143 return r;
2144
2229f656
LP
2145 r = fflush_and_check(f);
2146 if (r < 0)
2147 return r;
ceb728cf 2148
2e59b241 2149 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2229f656
LP
2150 if (strv_isempty(l)) {
2151 c->environment_files = strv_free(c->environment_files);
2e59b241 2152 unit_write_setting(u, flags, name, "EnvironmentFile=");
2229f656
LP
2153 } else {
2154 r = strv_extend_strv(&c->environment_files, l, true);
2155 if (r < 0)
2156 return r;
2157
2e59b241 2158 unit_write_setting(u, flags, name, joined);
2229f656
LP
2159 }
2160 }
ceb728cf 2161
ceb728cf
NC
2162 return 1;
2163
b4c14404
FB
2164 } else if (streq(name, "PassEnvironment")) {
2165
6171b822 2166 _cleanup_strv_free_ char **l = NULL;
b4c14404
FB
2167
2168 r = sd_bus_message_read_strv(message, &l);
2169 if (r < 0)
2170 return r;
2171
6171b822 2172 if (!strv_env_name_is_valid(l))
00819cc1 2173 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block.");
b4c14404 2174
2e59b241 2175 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
b4c14404
FB
2176 if (strv_isempty(l)) {
2177 c->pass_environment = strv_free(c->pass_environment);
2e59b241 2178 unit_write_setting(u, flags, name, "PassEnvironment=");
b4c14404
FB
2179 } else {
2180 _cleanup_free_ char *joined = NULL;
2181
9d4f242a
YW
2182 r = strv_extend_strv(&c->pass_environment, l, true);
2183 if (r < 0)
2184 return r;
2185
41de9cc2 2186 /* We write just the new settings out to file, with unresolved specifiers. */
2e59b241 2187 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
b4c14404
FB
2188 if (!joined)
2189 return -ENOMEM;
2190
2e59b241 2191 unit_write_settingf(u, flags, name, "PassEnvironment=%s", joined);
b4c14404
FB
2192 }
2193 }
2194
2195 return 1;
2196
2a624c36
AP
2197 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
2198 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) {
08596068
EV
2199 _cleanup_strv_free_ char **l = NULL;
2200 char ***dirs;
2201 char **p;
2202
2203 r = sd_bus_message_read_strv(message, &l);
2204 if (r < 0)
2205 return r;
2206
2207 STRV_FOREACH(p, l) {
e7bcff4e 2208 char *i = *p;
20b7a007
LP
2209 size_t offset;
2210
20b7a007
LP
2211 offset = i[0] == '-';
2212 offset += i[offset] == '+';
2213 if (!path_is_absolute(i + offset))
08596068 2214 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
e7bcff4e
YW
2215
2216 path_kill_slashes(i + offset);
08596068
EV
2217 }
2218
2e59b241 2219 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c4b41707
AP
2220 if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths"))
2221 dirs = &c->read_write_paths;
2222 else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
2223 dirs = &c->read_only_paths;
2224 else /* "InaccessiblePaths" */
2225 dirs = &c->inaccessible_paths;
08596068 2226
7b943bb7 2227 if (strv_isempty(l)) {
08596068 2228 *dirs = strv_free(*dirs);
2e59b241 2229 unit_write_settingf(u, flags, name, "%s=", name);
08596068 2230 } else {
2e59b241 2231 _cleanup_free_ char *joined = NULL;
08596068 2232
2e59b241 2233 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
08596068
EV
2234 if (!joined)
2235 return -ENOMEM;
2236
2e59b241
LP
2237 r = strv_extend_strv(dirs, l, true);
2238 if (r < 0)
2239 return -ENOMEM;
08596068 2240
2e59b241
LP
2241 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
2242 }
08596068
EV
2243 }
2244
2245 return 1;
2246
3536f49e 2247 } else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
fa21b5e3
EV
2248 _cleanup_strv_free_ char **l = NULL;
2249 char **p;
2250
2251 r = sd_bus_message_read_strv(message, &l);
2252 if (r < 0)
2253 return r;
2254
2255 STRV_FOREACH(p, l) {
99be45a4 2256 if (!path_is_normalized(*p) || path_is_absolute(*p))
091e9efe 2257 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not valid: %s", name, *p);
fa21b5e3
EV
2258 }
2259
2e59b241 2260 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
3536f49e
YW
2261 char ***dirs = NULL;
2262 ExecDirectoryType i;
2263
72fd1768 2264 for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++)
3536f49e
YW
2265 if (streq(name, exec_directory_type_to_string(i))) {
2266 dirs = &c->directories[i].paths;
2267 break;
2268 }
2269
2270 assert(dirs);
fa21b5e3
EV
2271
2272 if (strv_isempty(l)) {
3536f49e 2273 *dirs = strv_free(*dirs);
2e59b241 2274 unit_write_settingf(u, flags, name, "%s=", name);
fa21b5e3 2275 } else {
2e59b241
LP
2276 _cleanup_free_ char *joined = NULL;
2277
3536f49e 2278 r = strv_extend_strv(dirs, l, true);
fa21b5e3
EV
2279 if (r < 0)
2280 return -ENOMEM;
2281
2e59b241 2282 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
fa21b5e3
EV
2283 if (!joined)
2284 return -ENOMEM;
2285
2e59b241 2286 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
fa21b5e3
EV
2287 }
2288 }
2289
2290 return 1;
2291
cffaed83
YW
2292 } else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
2293 int ignore;
2294 const char *s;
2295
280921f2 2296 r = sd_bus_message_read(message, "(bs)", &ignore, &s);
cffaed83
YW
2297 if (r < 0)
2298 return r;
2299
2e59b241 2300 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cffaed83
YW
2301 char **p;
2302 bool *b;
2303
2304 if (streq(name, "AppArmorProfile")) {
2305 p = &c->apparmor_profile;
2306 b = &c->apparmor_profile_ignore;
2307 } else { /* "SmackProcessLabel" */
2308 p = &c->smack_process_label;
2309 b = &c->smack_process_label_ignore;
2310 }
2311
2312 if (isempty(s)) {
2313 *p = mfree(*p);
2314 *b = false;
2315 } else {
2316 if (free_and_strdup(p, s) < 0)
2317 return -ENOMEM;
2318 *b = ignore;
2319 }
2320
2e59b241 2321 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
cffaed83
YW
2322 }
2323
2324 return 1;
2325
d2d6c096 2326 } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
4ff4c98a
YW
2327 const char *source, *destination;
2328 int ignore_enoent;
2329 uint64_t mount_flags;
2330 bool empty = true;
d2d6c096
LP
2331
2332 r = sd_bus_message_enter_container(message, 'a', "(ssbt)");
2333 if (r < 0)
2334 return r;
2335
4ff4c98a 2336 while ((r = sd_bus_message_read(message, "(ssbt)", &source, &destination, &ignore_enoent, &mount_flags)) > 0) {
d2d6c096
LP
2337
2338 if (!path_is_absolute(source))
2339 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
2340 if (!path_is_absolute(destination))
91d910e3 2341 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
d2d6c096
LP
2342 if (!IN_SET(mount_flags, 0, MS_REC))
2343 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
2344
2e59b241 2345 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
d2d6c096
LP
2346 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
2347 &(BindMount) {
2348 .source = strdup(source),
2349 .destination = strdup(destination),
2350 .read_only = !!strstr(name, "ReadOnly"),
2351 .recursive = !!(mount_flags & MS_REC),
2352 .ignore_enoent = ignore_enoent,
2353 });
2354 if (r < 0)
2355 return r;
2356
2e59b241
LP
2357 unit_write_settingf(
2358 u, flags|UNIT_ESCAPE_SPECIFIERS, name,
d2d6c096
LP
2359 "%s=%s%s:%s:%s",
2360 name,
2361 ignore_enoent ? "-" : "",
2362 source,
2363 destination,
2364 (mount_flags & MS_REC) ? "rbind" : "norbind");
2365 }
2366
2367 empty = false;
2368 }
2369 if (r < 0)
2370 return r;
2371
2372 r = sd_bus_message_exit_container(message);
2373 if (r < 0)
2374 return r;
2375
2376 if (empty) {
2377 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
2378 c->bind_mounts = NULL;
2379 c->n_bind_mounts = 0;
2e59b241
LP
2380
2381 unit_write_settingf(u, flags, name, "%s=", name);
d2d6c096
LP
2382 }
2383
83555251
LP
2384 return 1;
2385 }
d2d6c096 2386
cab2aca3
LP
2387 ri = rlimit_from_string(name);
2388 if (ri < 0) {
2389 soft = endswith(name, "Soft");
2390 if (soft) {
2391 const char *n;
2392
2393 n = strndupa(name, soft - name);
2394 ri = rlimit_from_string(n);
2395 if (ri >= 0)
2396 name = n;
2397
2398 }
2399 }
2400
2401 if (ri >= 0) {
d584f638
LP
2402 uint64_t rl;
2403 rlim_t x;
2404
2405 r = sd_bus_message_read(message, "t", &rl);
2406 if (r < 0)
2407 return r;
2408
2409 if (rl == (uint64_t) -1)
2410 x = RLIM_INFINITY;
2411 else {
2412 x = (rlim_t) rl;
2413
2414 if ((uint64_t) x != rl)
2415 return -ERANGE;
2416 }
2417
2e59b241 2418 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cab2aca3
LP
2419 _cleanup_free_ char *f = NULL;
2420 struct rlimit nl;
2421
2422 if (c->rlimit[ri]) {
2423 nl = *c->rlimit[ri];
2424
2425 if (soft)
2426 nl.rlim_cur = x;
2427 else
2428 nl.rlim_max = x;
2429 } else
2430 /* When the resource limit is not initialized yet, then assign the value to both fields */
2431 nl = (struct rlimit) {
2432 .rlim_cur = x,
2433 .rlim_max = x,
2434 };
2435
2436 r = rlimit_format(&nl, &f);
2437 if (r < 0)
2438 return r;
d584f638 2439
cab2aca3
LP
2440 if (c->rlimit[ri])
2441 *c->rlimit[ri] = nl;
2442 else {
2443 c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
2444 if (!c->rlimit[ri])
d584f638
LP
2445 return -ENOMEM;
2446 }
2447
2e59b241 2448 unit_write_settingf(u, flags, name, "%s=%s", name, f);
d584f638
LP
2449 }
2450
c7040b5d
LP
2451 return 1;
2452 }
2453
2454 return 0;
2455}