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