]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
Merge pull request #6577 from poettering/more-exec-flags
[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("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
857 SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
858 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].mode), SD_BUS_VTABLE_PROPERTY_CONST),
859 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].paths), SD_BUS_VTABLE_PROPERTY_CONST),
860 SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
861 SD_BUS_PROPERTY("StateDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
862 SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
863 SD_BUS_PROPERTY("CacheDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
864 SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST),
865 SD_BUS_PROPERTY("LogsDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].paths), SD_BUS_VTABLE_PROPERTY_CONST),
866 SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST),
867 SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST),
868 SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
869 SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
870 SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
871 SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
872 SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
873 SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST),
874
875 /* Obsolete/redundant properties: */
876 SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
877 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
878 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
879 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
880 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
881
882 SD_BUS_VTABLE_END
883 };
884
885 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
886 int r;
887
888 assert(reply);
889 assert(c);
890
891 if (!c->path)
892 return 0;
893
894 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
895 if (r < 0)
896 return r;
897
898 r = sd_bus_message_append(reply, "s", c->path);
899 if (r < 0)
900 return r;
901
902 r = sd_bus_message_append_strv(reply, c->argv);
903 if (r < 0)
904 return r;
905
906 r = sd_bus_message_append(reply, "bttttuii",
907 !!(c->flags & EXEC_COMMAND_IGNORE_FAILURE),
908 c->exec_status.start_timestamp.realtime,
909 c->exec_status.start_timestamp.monotonic,
910 c->exec_status.exit_timestamp.realtime,
911 c->exec_status.exit_timestamp.monotonic,
912 (uint32_t) c->exec_status.pid,
913 (int32_t) c->exec_status.code,
914 (int32_t) c->exec_status.status);
915 if (r < 0)
916 return r;
917
918 return sd_bus_message_close_container(reply);
919 }
920
921 int bus_property_get_exec_command(
922 sd_bus *bus,
923 const char *path,
924 const char *interface,
925 const char *property,
926 sd_bus_message *reply,
927 void *userdata,
928 sd_bus_error *ret_error) {
929
930 ExecCommand *c = (ExecCommand*) userdata;
931 int r;
932
933 assert(bus);
934 assert(reply);
935
936 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
937 if (r < 0)
938 return r;
939
940 r = append_exec_command(reply, c);
941 if (r < 0)
942 return r;
943
944 return sd_bus_message_close_container(reply);
945 }
946
947 int bus_property_get_exec_command_list(
948 sd_bus *bus,
949 const char *path,
950 const char *interface,
951 const char *property,
952 sd_bus_message *reply,
953 void *userdata,
954 sd_bus_error *ret_error) {
955
956 ExecCommand *c = *(ExecCommand**) userdata;
957 int r;
958
959 assert(bus);
960 assert(reply);
961
962 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
963 if (r < 0)
964 return r;
965
966 LIST_FOREACH(command, c, c) {
967 r = append_exec_command(reply, c);
968 if (r < 0)
969 return r;
970 }
971
972 return sd_bus_message_close_container(reply);
973 }
974
975 int bus_exec_context_set_transient_property(
976 Unit *u,
977 ExecContext *c,
978 const char *name,
979 sd_bus_message *message,
980 UnitSetPropertiesMode mode,
981 sd_bus_error *error) {
982
983 const char *soft = NULL;
984 int r, ri;
985
986 assert(u);
987 assert(c);
988 assert(name);
989 assert(message);
990
991 if (streq(name, "User")) {
992 const char *uu;
993
994 r = sd_bus_message_read(message, "s", &uu);
995 if (r < 0)
996 return r;
997
998 if (!isempty(uu) && !valid_user_group_name_or_id(uu))
999 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user name: %s", uu);
1000
1001 if (mode != UNIT_CHECK) {
1002
1003 if (isempty(uu))
1004 c->user = mfree(c->user);
1005 else if (free_and_strdup(&c->user, uu) < 0)
1006 return -ENOMEM;
1007
1008 unit_write_drop_in_private_format(u, mode, name, "User=%s", uu);
1009 }
1010
1011 return 1;
1012
1013 } else if (streq(name, "Group")) {
1014 const char *gg;
1015
1016 r = sd_bus_message_read(message, "s", &gg);
1017 if (r < 0)
1018 return r;
1019
1020 if (!isempty(gg) && !valid_user_group_name_or_id(gg))
1021 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group name: %s", gg);
1022
1023 if (mode != UNIT_CHECK) {
1024
1025 if (isempty(gg))
1026 c->group = mfree(c->group);
1027 else if (free_and_strdup(&c->group, gg) < 0)
1028 return -ENOMEM;
1029
1030 unit_write_drop_in_private_format(u, mode, name, "Group=%s", gg);
1031 }
1032
1033 return 1;
1034
1035 } else if (streq(name, "SupplementaryGroups")) {
1036 _cleanup_strv_free_ char **l = NULL;
1037 char **p;
1038
1039 r = sd_bus_message_read_strv(message, &l);
1040 if (r < 0)
1041 return r;
1042
1043 STRV_FOREACH(p, l) {
1044 if (!isempty(*p) && !valid_user_group_name_or_id(*p))
1045 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid supplementary group names");
1046 }
1047
1048 if (mode != UNIT_CHECK) {
1049 if (strv_length(l) == 0) {
1050 c->supplementary_groups = strv_free(c->supplementary_groups);
1051 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
1052 } else {
1053 _cleanup_free_ char *joined = NULL;
1054
1055 r = strv_extend_strv(&c->supplementary_groups, l, true);
1056 if (r < 0)
1057 return -ENOMEM;
1058
1059 joined = strv_join(c->supplementary_groups, " ");
1060 if (!joined)
1061 return -ENOMEM;
1062
1063 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
1064 }
1065 }
1066
1067 return 1;
1068
1069 } else if (streq(name, "SyslogIdentifier")) {
1070 const char *id;
1071
1072 r = sd_bus_message_read(message, "s", &id);
1073 if (r < 0)
1074 return r;
1075
1076 if (mode != UNIT_CHECK) {
1077
1078 if (isempty(id))
1079 c->syslog_identifier = mfree(c->syslog_identifier);
1080 else if (free_and_strdup(&c->syslog_identifier, id) < 0)
1081 return -ENOMEM;
1082
1083 unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s", id);
1084 }
1085
1086 return 1;
1087 } else if (streq(name, "SyslogLevel")) {
1088 int32_t level;
1089
1090 r = sd_bus_message_read(message, "i", &level);
1091 if (r < 0)
1092 return r;
1093
1094 if (!log_level_is_valid(level))
1095 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
1096
1097 if (mode != UNIT_CHECK) {
1098 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
1099 unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i", level);
1100 }
1101
1102 return 1;
1103 } else if (streq(name, "SyslogFacility")) {
1104 int32_t facility;
1105
1106 r = sd_bus_message_read(message, "i", &facility);
1107 if (r < 0)
1108 return r;
1109
1110 if (!log_facility_unshifted_is_valid(facility))
1111 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
1112
1113 if (mode != UNIT_CHECK) {
1114 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
1115 unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i", facility);
1116 }
1117
1118 return 1;
1119 } else if (streq(name, "SecureBits")) {
1120 int n;
1121
1122 r = sd_bus_message_read(message, "i", &n);
1123 if (r < 0)
1124 return r;
1125
1126 if (!secure_bits_is_valid(n))
1127 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid secure bits");
1128
1129 if (mode != UNIT_CHECK) {
1130 _cleanup_free_ char *str = NULL;
1131
1132 c->secure_bits = n;
1133 r = secure_bits_to_string_alloc(n, &str);
1134 if (r < 0)
1135 return r;
1136
1137 unit_write_drop_in_private_format(u, mode, name, "SecureBits=%s", str);
1138 }
1139
1140 return 1;
1141 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
1142 uint64_t n;
1143
1144 r = sd_bus_message_read(message, "t", &n);
1145 if (r < 0)
1146 return r;
1147
1148 if (mode != UNIT_CHECK) {
1149 _cleanup_free_ char *str = NULL;
1150
1151 if (streq(name, "CapabilityBoundingSet"))
1152 c->capability_bounding_set = n;
1153 else /* "AmbientCapabilities" */
1154 c->capability_ambient_set = n;
1155
1156 r = capability_set_to_string_alloc(n, &str);
1157 if (r < 0)
1158 return r;
1159
1160 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
1161 }
1162
1163 return 1;
1164
1165 } else if (streq(name, "Personality")) {
1166 const char *s;
1167 unsigned long p;
1168
1169 r = sd_bus_message_read(message, "s", &s);
1170 if (r < 0)
1171 return r;
1172
1173 p = personality_from_string(s);
1174 if (p == PERSONALITY_INVALID)
1175 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid personality");
1176
1177 if (mode != UNIT_CHECK) {
1178 _cleanup_free_ char *str = NULL;
1179
1180 c->personality = p;
1181 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
1182 }
1183
1184 return 1;
1185
1186 #ifdef HAVE_SECCOMP
1187
1188 } else if (streq(name, "SystemCallFilter")) {
1189 int whitelist;
1190 _cleanup_strv_free_ char **l;
1191
1192 r = sd_bus_message_enter_container(message, 'r', "bas");
1193 if (r < 0)
1194 return r;
1195
1196 r = sd_bus_message_read(message, "b", &whitelist);
1197 if (r < 0)
1198 return r;
1199
1200 r = sd_bus_message_read_strv(message, &l);
1201 if (r < 0)
1202 return r;
1203
1204 r = sd_bus_message_exit_container(message);
1205 if (r < 0)
1206 return r;
1207
1208 if (mode != UNIT_CHECK) {
1209 _cleanup_free_ char *joined = NULL;
1210
1211 if (strv_length(l) == 0) {
1212 c->syscall_whitelist = false;
1213 c->syscall_filter = set_free(c->syscall_filter);
1214 } else {
1215 char **s;
1216
1217 c->syscall_whitelist = whitelist;
1218
1219 r = set_ensure_allocated(&c->syscall_filter, NULL);
1220 if (r < 0)
1221 return r;
1222
1223 STRV_FOREACH(s, l) {
1224 if (**s == '@') {
1225 const SyscallFilterSet *set;
1226 const char *i;
1227
1228 set = syscall_filter_set_find(*s);
1229 if (!set)
1230 return -EINVAL;
1231
1232 NULSTR_FOREACH(i, set->value) {
1233 int id;
1234
1235 id = seccomp_syscall_resolve_name(i);
1236 if (id == __NR_SCMP_ERROR)
1237 return -EINVAL;
1238
1239 r = set_put(c->address_families, INT_TO_PTR(id + 1));
1240 if (r < 0)
1241 return r;
1242 }
1243
1244 } else {
1245 int id;
1246
1247 id = seccomp_syscall_resolve_name(*s);
1248 if (id == __NR_SCMP_ERROR)
1249 return -EINVAL;
1250
1251 r = set_put(c->address_families, INT_TO_PTR(id + 1));
1252 if (r < 0)
1253 return r;
1254 }
1255 }
1256 }
1257
1258 joined = strv_join(l, " ");
1259 if (!joined)
1260 return -ENOMEM;
1261
1262 unit_write_drop_in_private_format(u, mode, name, "SystemCallFilter=%s%s", whitelist ? "" : "~", joined);
1263 }
1264
1265 return 1;
1266
1267 } else if (streq(name, "SystemCallArchitectures")) {
1268 _cleanup_strv_free_ char **l = NULL;
1269
1270 r = sd_bus_message_read_strv(message, &l);
1271 if (r < 0)
1272 return r;
1273
1274 if (mode != UNIT_CHECK) {
1275 _cleanup_free_ char *joined = NULL;
1276
1277 if (strv_length(l) == 0)
1278 c->syscall_archs = set_free(c->syscall_archs);
1279 else {
1280 char **s;
1281
1282 r = set_ensure_allocated(&c->syscall_archs, NULL);
1283 if (r < 0)
1284 return r;
1285
1286 STRV_FOREACH(s, l) {
1287 uint32_t a;
1288
1289 r = seccomp_arch_from_string(*s, &a);
1290 if (r < 0)
1291 return r;
1292
1293 r = set_put(c->syscall_archs, UINT32_TO_PTR(a + 1));
1294 if (r < 0)
1295 return r;
1296 }
1297
1298 }
1299
1300 joined = strv_join(l, " ");
1301 if (!joined)
1302 return -ENOMEM;
1303
1304 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
1305 }
1306
1307 return 1;
1308
1309 } else if (streq(name, "SystemCallErrorNumber")) {
1310 int32_t n;
1311 const char *str;
1312
1313 r = sd_bus_message_read(message, "i", &n);
1314 if (r < 0)
1315 return r;
1316
1317 str = errno_to_name(n);
1318 if (!str)
1319 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SystemCallErrorNumber");
1320
1321 if (mode != UNIT_CHECK) {
1322 c->syscall_errno = n;
1323
1324 unit_write_drop_in_private_format(u, mode, name, "SystemCallErrorNumber=%s", str);
1325 }
1326
1327 return 1;
1328
1329 } else if (streq(name, "RestrictAddressFamilies")) {
1330 int whitelist;
1331 _cleanup_strv_free_ char **l;
1332
1333 r = sd_bus_message_enter_container(message, 'r', "bas");
1334 if (r < 0)
1335 return r;
1336
1337 r = sd_bus_message_read(message, "b", &whitelist);
1338 if (r < 0)
1339 return r;
1340
1341 r = sd_bus_message_read_strv(message, &l);
1342 if (r < 0)
1343 return r;
1344
1345 r = sd_bus_message_exit_container(message);
1346 if (r < 0)
1347 return r;
1348
1349 if (mode != UNIT_CHECK) {
1350 _cleanup_free_ char *joined = NULL;
1351
1352 if (strv_length(l) == 0) {
1353 c->address_families_whitelist = false;
1354 c->address_families = set_free(c->address_families);
1355 } else {
1356 char **s;
1357
1358 c->address_families_whitelist = whitelist;
1359
1360 r = set_ensure_allocated(&c->address_families, NULL);
1361 if (r < 0)
1362 return r;
1363
1364 STRV_FOREACH(s, l) {
1365 int af;
1366
1367 af = af_from_name(*s);
1368 if (af <= 0)
1369 return -EINVAL;
1370
1371 r = set_put(c->address_families, INT_TO_PTR(af));
1372 if (r < 0)
1373 return r;
1374 }
1375 }
1376
1377 joined = strv_join(l, " ");
1378 if (!joined)
1379 return -ENOMEM;
1380
1381 unit_write_drop_in_private_format(u, mode, name, "RestrictAddressFamilies=%s%s", whitelist ? "" : "~", joined);
1382 }
1383
1384 return 1;
1385 #endif
1386
1387 } else if (streq(name, "CPUSchedulingPolicy")) {
1388 int32_t n;
1389
1390 r = sd_bus_message_read(message, "i", &n);
1391 if (r < 0)
1392 return r;
1393
1394 if (!sched_policy_is_valid(n))
1395 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy");
1396
1397 if (mode != UNIT_CHECK) {
1398 _cleanup_free_ char *str = NULL;
1399
1400 c->cpu_sched_policy = n;
1401 r = sched_policy_to_string_alloc(n, &str);
1402 if (r < 0)
1403 return r;
1404
1405 unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPolicy=%s", str);
1406 }
1407
1408 return 1;
1409
1410 } else if (streq(name, "CPUSchedulingPriority")) {
1411 int32_t n;
1412
1413 r = sd_bus_message_read(message, "i", &n);
1414 if (r < 0)
1415 return r;
1416
1417 if (!ioprio_priority_is_valid(n))
1418 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority");
1419
1420 if (mode != UNIT_CHECK) {
1421 c->cpu_sched_priority = n;
1422 unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPriority=%i", n);
1423 }
1424
1425 return 1;
1426
1427 } else if (streq(name, "CPUAffinity")) {
1428 const void *a;
1429 size_t n = 0;
1430
1431 r = sd_bus_message_read_array(message, 'y', &a, &n);
1432 if (r < 0)
1433 return r;
1434
1435 if (mode != UNIT_CHECK) {
1436 if (n == 0) {
1437 c->cpuset = mfree(c->cpuset);
1438 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
1439 } else {
1440 _cleanup_free_ char *str = NULL;
1441 uint8_t *l;
1442 size_t allocated = 0, len = 0, i;
1443
1444 c->cpuset = (cpu_set_t*) memdup(a, sizeof(cpu_set_t) * n);
1445 if (c->cpuset)
1446 return -ENOMEM;
1447
1448 l = (uint8_t*) a;
1449 for (i = 0; i < n; i++) {
1450 _cleanup_free_ char *p = NULL;
1451 size_t add;
1452
1453 r = asprintf(&p, "%hhi", l[i]);
1454 if (r < 0)
1455 return -ENOMEM;
1456
1457 add = strlen(p);
1458
1459 if (GREEDY_REALLOC(str, allocated, len + add + 2))
1460 return -ENOMEM;
1461
1462 strcpy(mempcpy(str + len, p, add), " ");
1463 len += add + 1;
1464 }
1465
1466 if (len != 0)
1467 str[len - 1] = '\0';
1468
1469 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
1470 }
1471 }
1472
1473 return 1;
1474 } else if (streq(name, "Nice")) {
1475 int32_t n;
1476
1477 r = sd_bus_message_read(message, "i", &n);
1478 if (r < 0)
1479 return r;
1480
1481 if (!nice_is_valid(n))
1482 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
1483
1484 if (mode != UNIT_CHECK) {
1485 c->nice = n;
1486 unit_write_drop_in_private_format(u, mode, name, "Nice=%i", n);
1487 }
1488
1489 return 1;
1490
1491 } else if (streq(name, "IOSchedulingClass")) {
1492 int32_t q;
1493
1494 r = sd_bus_message_read(message, "i", &q);
1495 if (r < 0)
1496 return r;
1497
1498 if (!ioprio_class_is_valid(q))
1499 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q);
1500
1501 if (mode != UNIT_CHECK) {
1502 _cleanup_free_ char *s = NULL;
1503
1504 r = ioprio_class_to_string_alloc(q, &s);
1505 if (r < 0)
1506 return r;
1507
1508 c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio));
1509 c->ioprio_set = true;
1510
1511 unit_write_drop_in_private_format(u, mode, name, "IOSchedulingClass=%s", s);
1512 }
1513
1514 return 1;
1515
1516 } else if (streq(name, "IOSchedulingPriority")) {
1517 int32_t p;
1518
1519 r = sd_bus_message_read(message, "i", &p);
1520 if (r < 0)
1521 return r;
1522
1523 if (!ioprio_priority_is_valid(p))
1524 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
1525
1526 if (mode != UNIT_CHECK) {
1527 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p);
1528 c->ioprio_set = true;
1529
1530 unit_write_drop_in_private_format(u, mode, name, "IOSchedulingPriority=%i", p);
1531 }
1532
1533 return 1;
1534
1535 } else if (STR_IN_SET(name, "TTYPath", "RootDirectory", "RootImage")) {
1536 const char *s;
1537
1538 r = sd_bus_message_read(message, "s", &s);
1539 if (r < 0)
1540 return r;
1541
1542 if (!path_is_absolute(s))
1543 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
1544
1545 if (mode != UNIT_CHECK) {
1546 if (streq(name, "TTYPath"))
1547 r = free_and_strdup(&c->tty_path, s);
1548 else if (streq(name, "RootImage"))
1549 r = free_and_strdup(&c->root_image, s);
1550 else {
1551 assert(streq(name, "RootDirectory"));
1552 r = free_and_strdup(&c->root_directory, s);
1553 }
1554 if (r < 0)
1555 return r;
1556
1557 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
1558 }
1559
1560 return 1;
1561
1562 } else if (streq(name, "WorkingDirectory")) {
1563 const char *s;
1564 bool missing_ok;
1565
1566 r = sd_bus_message_read(message, "s", &s);
1567 if (r < 0)
1568 return r;
1569
1570 if (s[0] == '-') {
1571 missing_ok = true;
1572 s++;
1573 } else
1574 missing_ok = false;
1575
1576 if (!streq(s, "~") && !path_is_absolute(s))
1577 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
1578
1579 if (mode != UNIT_CHECK) {
1580 if (streq(s, "~")) {
1581 c->working_directory = mfree(c->working_directory);
1582 c->working_directory_home = true;
1583 } else {
1584 r = free_and_strdup(&c->working_directory, s);
1585 if (r < 0)
1586 return r;
1587
1588 c->working_directory_home = false;
1589 }
1590
1591 c->working_directory_missing_ok = missing_ok;
1592 unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
1593 }
1594
1595 return 1;
1596
1597 } else if (streq(name, "StandardInput")) {
1598 const char *s;
1599 ExecInput p;
1600
1601 r = sd_bus_message_read(message, "s", &s);
1602 if (r < 0)
1603 return r;
1604
1605 p = exec_input_from_string(s);
1606 if (p < 0)
1607 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
1608
1609 if (mode != UNIT_CHECK) {
1610 c->std_input = p;
1611
1612 unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s", exec_input_to_string(p));
1613 }
1614
1615 return 1;
1616
1617 } else if (streq(name, "StandardOutput")) {
1618 const char *s;
1619 ExecOutput p;
1620
1621 r = sd_bus_message_read(message, "s", &s);
1622 if (r < 0)
1623 return r;
1624
1625 p = exec_output_from_string(s);
1626 if (p < 0)
1627 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
1628
1629 if (mode != UNIT_CHECK) {
1630 c->std_output = p;
1631
1632 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s", exec_output_to_string(p));
1633 }
1634
1635 return 1;
1636
1637 } else if (streq(name, "StandardError")) {
1638 const char *s;
1639 ExecOutput p;
1640
1641 r = sd_bus_message_read(message, "s", &s);
1642 if (r < 0)
1643 return r;
1644
1645 p = exec_output_from_string(s);
1646 if (p < 0)
1647 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
1648
1649 if (mode != UNIT_CHECK) {
1650 c->std_error = p;
1651
1652 unit_write_drop_in_private_format(u, mode, name, "StandardError=%s", exec_output_to_string(p));
1653 }
1654
1655 return 1;
1656
1657 } else if (STR_IN_SET(name,
1658 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
1659 const char *s;
1660
1661 r = sd_bus_message_read(message, "s", &s);
1662 if (r < 0)
1663 return r;
1664
1665 if (!fdname_is_valid(s))
1666 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
1667
1668 if (mode != UNIT_CHECK) {
1669 if (streq(name, "StandardInputFileDescriptorName")) {
1670 c->std_input = EXEC_INPUT_NAMED_FD;
1671 r = free_and_strdup(&c->stdio_fdname[STDIN_FILENO], s);
1672 if (r < 0)
1673 return r;
1674 unit_write_drop_in_private_format(u, mode, name, "StandardInput=fd:%s", s);
1675 } else if (streq(name, "StandardOutputFileDescriptorName")) {
1676 c->std_output = EXEC_OUTPUT_NAMED_FD;
1677 r = free_and_strdup(&c->stdio_fdname[STDOUT_FILENO], s);
1678 if (r < 0)
1679 return r;
1680 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=fd:%s", s);
1681 } else if (streq(name, "StandardErrorFileDescriptorName")) {
1682 c->std_error = EXEC_OUTPUT_NAMED_FD;
1683 r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], s);
1684 if (r < 0)
1685 return r;
1686 unit_write_drop_in_private_format(u, mode, name, "StandardError=fd:%s", s);
1687 }
1688 }
1689
1690 return 1;
1691
1692 } else if (STR_IN_SET(name,
1693 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate",
1694 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers",
1695 "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute",
1696 "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables",
1697 "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS",
1698 "CPUSchedulingResetOnFork", "NonBlocking")) {
1699 int b;
1700
1701 r = sd_bus_message_read(message, "b", &b);
1702 if (r < 0)
1703 return r;
1704
1705 if (mode != UNIT_CHECK) {
1706 if (streq(name, "IgnoreSIGPIPE"))
1707 c->ignore_sigpipe = b;
1708 else if (streq(name, "TTYVHangup"))
1709 c->tty_vhangup = b;
1710 else if (streq(name, "TTYReset"))
1711 c->tty_reset = b;
1712 else if (streq(name, "TTYVTDisallocate"))
1713 c->tty_vt_disallocate = b;
1714 else if (streq(name, "PrivateTmp"))
1715 c->private_tmp = b;
1716 else if (streq(name, "PrivateDevices"))
1717 c->private_devices = b;
1718 else if (streq(name, "PrivateNetwork"))
1719 c->private_network = b;
1720 else if (streq(name, "PrivateUsers"))
1721 c->private_users = b;
1722 else if (streq(name, "NoNewPrivileges"))
1723 c->no_new_privileges = b;
1724 else if (streq(name, "SyslogLevelPrefix"))
1725 c->syslog_level_prefix = b;
1726 else if (streq(name, "MemoryDenyWriteExecute"))
1727 c->memory_deny_write_execute = b;
1728 else if (streq(name, "RestrictRealtime"))
1729 c->restrict_realtime = b;
1730 else if (streq(name, "DynamicUser"))
1731 c->dynamic_user = b;
1732 else if (streq(name, "RemoveIPC"))
1733 c->remove_ipc = b;
1734 else if (streq(name, "ProtectKernelTunables"))
1735 c->protect_kernel_tunables = b;
1736 else if (streq(name, "ProtectKernelModules"))
1737 c->protect_kernel_modules = b;
1738 else if (streq(name, "ProtectControlGroups"))
1739 c->protect_control_groups = b;
1740 else if (streq(name, "MountAPIVFS"))
1741 c->mount_apivfs = b;
1742 else if (streq(name, "CPUSchedulingResetOnFork"))
1743 c->cpu_sched_reset_on_fork = b;
1744 else if (streq(name, "NonBlocking"))
1745 c->non_blocking = b;
1746
1747 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, yes_no(b));
1748 }
1749
1750 return 1;
1751
1752 } else if (streq(name, "UtmpIdentifier")) {
1753 const char *id;
1754
1755 r = sd_bus_message_read(message, "s", &id);
1756 if (r < 0)
1757 return r;
1758
1759 if (mode != UNIT_CHECK) {
1760 if (isempty(id))
1761 c->utmp_id = mfree(c->utmp_id);
1762 else if (free_and_strdup(&c->utmp_id, id) < 0)
1763 return -ENOMEM;
1764
1765 unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s", strempty(id));
1766 }
1767
1768 return 1;
1769
1770 } else if (streq(name, "UtmpMode")) {
1771 const char *s;
1772 ExecUtmpMode m;
1773
1774 r = sd_bus_message_read(message, "s", &s);
1775 if (r < 0)
1776 return r;
1777
1778 m = exec_utmp_mode_from_string(s);
1779 if (m < 0)
1780 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
1781
1782 if (mode != UNIT_CHECK) {
1783 c->utmp_mode = m;
1784
1785 unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s", exec_utmp_mode_to_string(m));
1786 }
1787
1788 return 1;
1789
1790 } else if (streq(name, "PAMName")) {
1791 const char *n;
1792
1793 r = sd_bus_message_read(message, "s", &n);
1794 if (r < 0)
1795 return r;
1796
1797 if (mode != UNIT_CHECK) {
1798 if (isempty(n))
1799 c->pam_name = mfree(c->pam_name);
1800 else if (free_and_strdup(&c->pam_name, n) < 0)
1801 return -ENOMEM;
1802
1803 unit_write_drop_in_private_format(u, mode, name, "PAMName=%s", strempty(n));
1804 }
1805
1806 return 1;
1807
1808 } else if (streq(name, "Environment")) {
1809
1810 _cleanup_strv_free_ char **l = NULL, **q = NULL;
1811
1812 r = sd_bus_message_read_strv(message, &l);
1813 if (r < 0)
1814 return r;
1815
1816 if (!strv_env_is_valid(l))
1817 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1818
1819 r = unit_full_printf_strv(u, l, &q);
1820 if (r < 0)
1821 return r;
1822
1823 if (mode != UNIT_CHECK) {
1824 if (strv_length(q) == 0) {
1825 c->environment = strv_free(c->environment);
1826 unit_write_drop_in_private_format(u, mode, name, "Environment=");
1827 } else {
1828 _cleanup_free_ char *joined = NULL;
1829 char **e;
1830
1831 e = strv_env_merge(2, c->environment, q);
1832 if (!e)
1833 return -ENOMEM;
1834
1835 strv_free(c->environment);
1836 c->environment = e;
1837
1838 /* We write just the new settings out to file, with unresolved specifiers */
1839 joined = strv_join_quoted(q);
1840 if (!joined)
1841 return -ENOMEM;
1842
1843 unit_write_drop_in_private_format(u, mode, name, "Environment=%s", joined);
1844 }
1845 }
1846
1847 return 1;
1848
1849 } else if (streq(name, "TimerSlackNSec")) {
1850
1851 nsec_t n;
1852
1853 r = sd_bus_message_read(message, "t", &n);
1854 if (r < 0)
1855 return r;
1856
1857 if (mode != UNIT_CHECK) {
1858 c->timer_slack_nsec = n;
1859 unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT, n);
1860 }
1861
1862 return 1;
1863
1864 } else if (streq(name, "OOMScoreAdjust")) {
1865 int oa;
1866
1867 r = sd_bus_message_read(message, "i", &oa);
1868 if (r < 0)
1869 return r;
1870
1871 if (!oom_score_adjust_is_valid(oa))
1872 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
1873
1874 if (mode != UNIT_CHECK) {
1875 c->oom_score_adjust = oa;
1876 c->oom_score_adjust_set = true;
1877 unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i", oa);
1878 }
1879
1880 return 1;
1881
1882 } else if (streq(name, "EnvironmentFiles")) {
1883
1884 _cleanup_free_ char *joined = NULL;
1885 _cleanup_fclose_ FILE *f = NULL;
1886 _cleanup_strv_free_ char **l = NULL;
1887 size_t size = 0;
1888 char **i;
1889
1890 r = sd_bus_message_enter_container(message, 'a', "(sb)");
1891 if (r < 0)
1892 return r;
1893
1894 f = open_memstream(&joined, &size);
1895 if (!f)
1896 return -ENOMEM;
1897
1898 STRV_FOREACH(i, c->environment_files)
1899 fprintf(f, "EnvironmentFile=%s", *i);
1900
1901 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
1902 const char *path;
1903 int b;
1904
1905 r = sd_bus_message_read(message, "sb", &path, &b);
1906 if (r < 0)
1907 return r;
1908
1909 r = sd_bus_message_exit_container(message);
1910 if (r < 0)
1911 return r;
1912
1913 if (!path_is_absolute(path))
1914 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
1915
1916 if (mode != UNIT_CHECK) {
1917 char *buf = NULL;
1918
1919 buf = strjoin(b ? "-" : "", path);
1920 if (!buf)
1921 return -ENOMEM;
1922
1923 fprintf(f, "EnvironmentFile=%s", buf);
1924
1925 r = strv_consume(&l, buf);
1926 if (r < 0)
1927 return r;
1928 }
1929 }
1930 if (r < 0)
1931 return r;
1932
1933 r = sd_bus_message_exit_container(message);
1934 if (r < 0)
1935 return r;
1936
1937 r = fflush_and_check(f);
1938 if (r < 0)
1939 return r;
1940
1941 if (mode != UNIT_CHECK) {
1942 if (strv_isempty(l)) {
1943 c->environment_files = strv_free(c->environment_files);
1944 unit_write_drop_in_private(u, mode, name, "EnvironmentFile=");
1945 } else {
1946 r = strv_extend_strv(&c->environment_files, l, true);
1947 if (r < 0)
1948 return r;
1949
1950 unit_write_drop_in_private(u, mode, name, joined);
1951 }
1952 }
1953
1954 return 1;
1955
1956 } else if (streq(name, "PassEnvironment")) {
1957
1958 _cleanup_strv_free_ char **l = NULL;
1959
1960 r = sd_bus_message_read_strv(message, &l);
1961 if (r < 0)
1962 return r;
1963
1964 if (!strv_env_name_is_valid(l))
1965 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment block.");
1966
1967 if (mode != UNIT_CHECK) {
1968 if (strv_isempty(l)) {
1969 c->pass_environment = strv_free(c->pass_environment);
1970 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=");
1971 } else {
1972 _cleanup_free_ char *joined = NULL;
1973
1974 r = strv_extend_strv(&c->pass_environment, l, true);
1975 if (r < 0)
1976 return r;
1977
1978 joined = strv_join_quoted(c->pass_environment);
1979 if (!joined)
1980 return -ENOMEM;
1981
1982 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=%s", joined);
1983 }
1984 }
1985
1986 return 1;
1987
1988 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
1989 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) {
1990 _cleanup_strv_free_ char **l = NULL;
1991 char ***dirs;
1992 char **p;
1993
1994 r = sd_bus_message_read_strv(message, &l);
1995 if (r < 0)
1996 return r;
1997
1998 STRV_FOREACH(p, l) {
1999 const char *i = *p;
2000 size_t offset;
2001
2002 if (!utf8_is_valid(i))
2003 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
2004
2005 offset = i[0] == '-';
2006 offset += i[offset] == '+';
2007 if (!path_is_absolute(i + offset))
2008 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
2009 }
2010
2011 if (mode != UNIT_CHECK) {
2012 _cleanup_free_ char *joined = NULL;
2013
2014 if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths"))
2015 dirs = &c->read_write_paths;
2016 else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
2017 dirs = &c->read_only_paths;
2018 else /* "InaccessiblePaths" */
2019 dirs = &c->inaccessible_paths;
2020
2021 if (strv_length(l) == 0) {
2022 *dirs = strv_free(*dirs);
2023 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
2024 } else {
2025 r = strv_extend_strv(dirs, l, true);
2026 if (r < 0)
2027 return -ENOMEM;
2028
2029 joined = strv_join_quoted(*dirs);
2030 if (!joined)
2031 return -ENOMEM;
2032
2033 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
2034 }
2035
2036 }
2037
2038 return 1;
2039
2040 } else if (streq(name, "ProtectSystem")) {
2041 const char *s;
2042 ProtectSystem ps;
2043
2044 r = sd_bus_message_read(message, "s", &s);
2045 if (r < 0)
2046 return r;
2047
2048 r = parse_boolean(s);
2049 if (r > 0)
2050 ps = PROTECT_SYSTEM_YES;
2051 else if (r == 0)
2052 ps = PROTECT_SYSTEM_NO;
2053 else {
2054 ps = protect_system_from_string(s);
2055 if (ps < 0)
2056 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value");
2057 }
2058
2059 if (mode != UNIT_CHECK) {
2060 c->protect_system = ps;
2061 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
2062 }
2063
2064 return 1;
2065
2066 } else if (streq(name, "ProtectHome")) {
2067 const char *s;
2068 ProtectHome ph;
2069
2070 r = sd_bus_message_read(message, "s", &s);
2071 if (r < 0)
2072 return r;
2073
2074 r = parse_boolean(s);
2075 if (r > 0)
2076 ph = PROTECT_HOME_YES;
2077 else if (r == 0)
2078 ph = PROTECT_HOME_NO;
2079 else {
2080 ph = protect_home_from_string(s);
2081 if (ph < 0)
2082 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value");
2083 }
2084
2085 if (mode != UNIT_CHECK) {
2086 c->protect_home = ph;
2087 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
2088 }
2089
2090 return 1;
2091
2092 } else if (streq(name, "RuntimeDirectoryPreserve")) {
2093 const char *s;
2094 ExecPreserveMode m;
2095
2096 r = sd_bus_message_read(message, "s", &s);
2097 if (r < 0)
2098 return r;
2099
2100 m = exec_preserve_mode_from_string(s);
2101 if (m < 0)
2102 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid preserve mode");
2103
2104 if (mode != UNIT_CHECK) {
2105 c->runtime_directory_preserve_mode = m;
2106
2107 unit_write_drop_in_private_format(u, mode, name, "RuntimeDirectoryPreserve=%s", exec_preserve_mode_to_string(m));
2108 }
2109
2110 return 1;
2111
2112 } else if (STR_IN_SET(name, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode", "UMask")) {
2113 mode_t m;
2114
2115 r = sd_bus_message_read(message, "u", &m);
2116 if (r < 0)
2117 return r;
2118
2119 if (mode != UNIT_CHECK) {
2120 ExecDirectoryType i;
2121
2122 if (streq(name, "UMask"))
2123 c->umask = m;
2124 else
2125 for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
2126 if (startswith(name, exec_directory_type_to_string(i))) {
2127 c->directories[i].mode = m;
2128 break;
2129 }
2130
2131 unit_write_drop_in_private_format(u, mode, name, "%s=%040o", name, m);
2132 }
2133
2134 return 1;
2135
2136 } else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
2137 _cleanup_strv_free_ char **l = NULL;
2138 char **p;
2139
2140 r = sd_bus_message_read_strv(message, &l);
2141 if (r < 0)
2142 return r;
2143
2144 STRV_FOREACH(p, l) {
2145 if (!filename_is_valid(*p))
2146 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s is not valid %s", name, *p);
2147 }
2148
2149 if (mode != UNIT_CHECK) {
2150 _cleanup_free_ char *joined = NULL;
2151 char ***dirs = NULL;
2152 ExecDirectoryType i;
2153
2154 for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
2155 if (streq(name, exec_directory_type_to_string(i))) {
2156 dirs = &c->directories[i].paths;
2157 break;
2158 }
2159
2160 assert(dirs);
2161
2162 if (strv_isempty(l)) {
2163 *dirs = strv_free(*dirs);
2164 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
2165 } else {
2166 r = strv_extend_strv(dirs, l, true);
2167
2168 if (r < 0)
2169 return -ENOMEM;
2170
2171 joined = strv_join_quoted(*dirs);
2172 if (!joined)
2173 return -ENOMEM;
2174
2175 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
2176 }
2177 }
2178
2179 return 1;
2180
2181 } else if (streq(name, "SELinuxContext")) {
2182 const char *s;
2183 r = sd_bus_message_read(message, "s", &s);
2184 if (r < 0)
2185 return r;
2186
2187 if (mode != UNIT_CHECK) {
2188 if (isempty(s))
2189 c->selinux_context = mfree(c->selinux_context);
2190 else if (free_and_strdup(&c->selinux_context, s) < 0)
2191 return -ENOMEM;
2192
2193 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, strempty(s));
2194 }
2195
2196 return 1;
2197
2198 } else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
2199 int ignore;
2200 const char *s;
2201
2202 r = sd_bus_message_enter_container(message, 'r', "bs");
2203 if (r < 0)
2204 return r;
2205
2206 r = sd_bus_message_read(message, "bs", &ignore, &s);
2207 if (r < 0)
2208 return r;
2209
2210 if (mode != UNIT_CHECK) {
2211 char **p;
2212 bool *b;
2213
2214 if (streq(name, "AppArmorProfile")) {
2215 p = &c->apparmor_profile;
2216 b = &c->apparmor_profile_ignore;
2217 } else { /* "SmackProcessLabel" */
2218 p = &c->smack_process_label;
2219 b = &c->smack_process_label_ignore;
2220 }
2221
2222 if (isempty(s)) {
2223 *p = mfree(*p);
2224 *b = false;
2225 } else {
2226 if (free_and_strdup(p, s) < 0)
2227 return -ENOMEM;
2228 *b = ignore;
2229 }
2230
2231 unit_write_drop_in_private_format(u, mode, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
2232 }
2233
2234 return 1;
2235
2236 } else if (streq(name, "RestrictNamespaces")) {
2237 uint64_t flags;
2238
2239 r = sd_bus_message_read(message, "t", &flags);
2240 if (r < 0)
2241 return r;
2242 if ((flags & NAMESPACE_FLAGS_ALL) != flags)
2243 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown namespace types");
2244
2245 if (mode != UNIT_CHECK) {
2246 _cleanup_free_ char *s = NULL;
2247
2248 r = namespace_flag_to_string_many(flags, &s);
2249 if (r < 0)
2250 return r;
2251
2252 c->restrict_namespaces = flags;
2253 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
2254 }
2255
2256 return 1;
2257 } else if (streq(name, "MountFlags")) {
2258 uint64_t flags;
2259
2260 r = sd_bus_message_read(message, "t", &flags);
2261 if (r < 0)
2262 return r;
2263 if (!IN_SET(flags, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
2264 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount propagation flags");
2265
2266 if (mode != UNIT_CHECK) {
2267 c->mount_flags = flags;
2268
2269 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, mount_propagation_flags_to_string(flags));
2270 }
2271
2272 return 1;
2273 } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
2274 unsigned empty = true;
2275
2276 r = sd_bus_message_enter_container(message, 'a', "(ssbt)");
2277 if (r < 0)
2278 return r;
2279
2280 while ((r = sd_bus_message_enter_container(message, 'r', "ssbt")) > 0) {
2281 const char *source, *destination;
2282 int ignore_enoent;
2283 uint64_t mount_flags;
2284
2285 r = sd_bus_message_read(message, "ssbt", &source, &destination, &ignore_enoent, &mount_flags);
2286 if (r < 0)
2287 return r;
2288
2289 r = sd_bus_message_exit_container(message);
2290 if (r < 0)
2291 return r;
2292
2293 if (!path_is_absolute(source))
2294 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
2295 if (!path_is_absolute(destination))
2296 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
2297 if (!IN_SET(mount_flags, 0, MS_REC))
2298 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
2299
2300 if (mode != UNIT_CHECK) {
2301 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
2302 &(BindMount) {
2303 .source = strdup(source),
2304 .destination = strdup(destination),
2305 .read_only = !!strstr(name, "ReadOnly"),
2306 .recursive = !!(mount_flags & MS_REC),
2307 .ignore_enoent = ignore_enoent,
2308 });
2309 if (r < 0)
2310 return r;
2311
2312 unit_write_drop_in_private_format(
2313 u, mode, name,
2314 "%s=%s%s:%s:%s",
2315 name,
2316 ignore_enoent ? "-" : "",
2317 source,
2318 destination,
2319 (mount_flags & MS_REC) ? "rbind" : "norbind");
2320 }
2321
2322 empty = false;
2323 }
2324 if (r < 0)
2325 return r;
2326
2327 r = sd_bus_message_exit_container(message);
2328 if (r < 0)
2329 return r;
2330
2331 if (empty) {
2332 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
2333 c->bind_mounts = NULL;
2334 c->n_bind_mounts = 0;
2335 }
2336
2337 return 1;
2338 }
2339
2340 ri = rlimit_from_string(name);
2341 if (ri < 0) {
2342 soft = endswith(name, "Soft");
2343 if (soft) {
2344 const char *n;
2345
2346 n = strndupa(name, soft - name);
2347 ri = rlimit_from_string(n);
2348 if (ri >= 0)
2349 name = n;
2350
2351 }
2352 }
2353
2354 if (ri >= 0) {
2355 uint64_t rl;
2356 rlim_t x;
2357
2358 r = sd_bus_message_read(message, "t", &rl);
2359 if (r < 0)
2360 return r;
2361
2362 if (rl == (uint64_t) -1)
2363 x = RLIM_INFINITY;
2364 else {
2365 x = (rlim_t) rl;
2366
2367 if ((uint64_t) x != rl)
2368 return -ERANGE;
2369 }
2370
2371 if (mode != UNIT_CHECK) {
2372 _cleanup_free_ char *f = NULL;
2373 struct rlimit nl;
2374
2375 if (c->rlimit[ri]) {
2376 nl = *c->rlimit[ri];
2377
2378 if (soft)
2379 nl.rlim_cur = x;
2380 else
2381 nl.rlim_max = x;
2382 } else
2383 /* When the resource limit is not initialized yet, then assign the value to both fields */
2384 nl = (struct rlimit) {
2385 .rlim_cur = x,
2386 .rlim_max = x,
2387 };
2388
2389 r = rlimit_format(&nl, &f);
2390 if (r < 0)
2391 return r;
2392
2393 if (c->rlimit[ri])
2394 *c->rlimit[ri] = nl;
2395 else {
2396 c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
2397 if (!c->rlimit[ri])
2398 return -ENOMEM;
2399 }
2400
2401 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, f);
2402 }
2403
2404 return 1;
2405 }
2406
2407 return 0;
2408 }