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