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