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