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