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