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