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