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