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