]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
core: make IOSchedulingClass= and IOSchedulingPriority= settable for transient units
[thirdparty/systemd.git] / src / core / dbus-execute.c
CommitLineData
4139c1b2
LP
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
5430f7f2
LP
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
4139c1b2
LP
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
5430f7f2 14 Lesser General Public License for more details.
4139c1b2 15
5430f7f2 16 You should have received a copy of the GNU Lesser General Public License
4139c1b2
LP
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
82c121a4 20#include <sys/prctl.h>
4139c1b2 21
57183d11
LP
22#ifdef HAVE_SECCOMP
23#include <seccomp.h>
24#endif
25
3ffd4af2 26#include "af-list.h"
b5efdb8a 27#include "alloc-util.h"
718db961 28#include "bus-util.h"
430f0182 29#include "capability-util.h"
3ffd4af2 30#include "dbus-execute.h"
c7040b5d 31#include "env-util.h"
3ffd4af2
LP
32#include "execute.h"
33#include "fd-util.h"
34#include "fileio.h"
35#include "ioprio.h"
36#include "missing.h"
83555251 37#include "mount-util.h"
417116f2 38#include "namespace.h"
6bedfcbb 39#include "parse-util.h"
9b15b784 40#include "path-util.h"
7b3e062c 41#include "process-util.h"
78f22b97 42#include "rlimit-util.h"
57183d11
LP
43#ifdef HAVE_SECCOMP
44#include "seccomp-util.h"
45#endif
6bedfcbb 46#include "strv.h"
7ccbd1ae 47#include "syslog-util.h"
f900f582 48#include "unit-printf.h"
6f3e7985 49#include "user-util.h"
6bedfcbb 50#include "utf8.h"
57183d11 51
718db961 52BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
82c121a4 53
718db961 54static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
8c7be95e 55
023a4f67
LP
56static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
57
1b8689f9
LP
58static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
59static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
417116f2 60
718db961
LP
61static int property_get_environment_files(
62 sd_bus *bus,
63 const char *path,
64 const char *interface,
65 const char *property,
66 sd_bus_message *reply,
ebcf1f97
LP
67 void *userdata,
68 sd_bus_error *error) {
8c7be95e 69
718db961
LP
70 ExecContext *c = userdata;
71 char **j;
72 int r;
8c7be95e 73
718db961
LP
74 assert(bus);
75 assert(reply);
76 assert(c);
77
78 r = sd_bus_message_open_container(reply, 'a', "(sb)");
79 if (r < 0)
80 return r;
8c7be95e 81
718db961
LP
82 STRV_FOREACH(j, c->environment_files) {
83 const char *fn = *j;
8c7be95e 84
718db961
LP
85 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
86 if (r < 0)
87 return r;
8c7be95e
LP
88 }
89
718db961
LP
90 return sd_bus_message_close_container(reply);
91}
92
718db961
LP
93static int property_get_oom_score_adjust(
94 sd_bus *bus,
95 const char *path,
96 const char *interface,
97 const char *property,
98 sd_bus_message *reply,
ebcf1f97
LP
99 void *userdata,
100 sd_bus_error *error) {
718db961
LP
101
102
103 ExecContext *c = userdata;
82c121a4
LP
104 int32_t n;
105
718db961
LP
106 assert(bus);
107 assert(reply);
82c121a4
LP
108 assert(c);
109
dd6c17b1
LP
110 if (c->oom_score_adjust_set)
111 n = c->oom_score_adjust;
82c121a4 112 else {
68eda4bd 113 _cleanup_free_ char *t = NULL;
82c121a4
LP
114
115 n = 0;
718db961 116 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
e4e73a63 117 safe_atoi32(t, &n);
82c121a4
LP
118 }
119
718db961 120 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
121}
122
718db961
LP
123static int property_get_nice(
124 sd_bus *bus,
125 const char *path,
126 const char *interface,
127 const char *property,
128 sd_bus_message *reply,
ebcf1f97
LP
129 void *userdata,
130 sd_bus_error *error) {
718db961
LP
131
132
133 ExecContext *c = userdata;
82c121a4
LP
134 int32_t n;
135
718db961
LP
136 assert(bus);
137 assert(reply);
82c121a4
LP
138 assert(c);
139
140 if (c->nice_set)
141 n = c->nice;
718db961
LP
142 else {
143 errno = 0;
82c121a4 144 n = getpriority(PRIO_PROCESS, 0);
b3267152 145 if (errno > 0)
718db961
LP
146 n = 0;
147 }
82c121a4 148
718db961 149 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
150}
151
718db961
LP
152static int property_get_ioprio(
153 sd_bus *bus,
154 const char *path,
155 const char *interface,
156 const char *property,
157 sd_bus_message *reply,
ebcf1f97
LP
158 void *userdata,
159 sd_bus_error *error) {
718db961
LP
160
161
162 ExecContext *c = userdata;
82c121a4 163
718db961
LP
164 assert(bus);
165 assert(reply);
82c121a4
LP
166 assert(c);
167
7f452159
LP
168 return sd_bus_message_append(reply, "i", exec_context_get_effective_ioprio(c));
169}
82c121a4 170
7f452159
LP
171static int property_get_ioprio_class(
172 sd_bus *bus,
173 const char *path,
174 const char *interface,
175 const char *property,
176 sd_bus_message *reply,
177 void *userdata,
178 sd_bus_error *error) {
179
180
181 ExecContext *c = userdata;
182
183 assert(bus);
184 assert(reply);
185 assert(c);
186
187 return sd_bus_message_append(reply, "i", IOPRIO_PRIO_CLASS(exec_context_get_effective_ioprio(c)));
188}
189
190
191static int property_get_ioprio_priority(
192 sd_bus *bus,
193 const char *path,
194 const char *interface,
195 const char *property,
196 sd_bus_message *reply,
197 void *userdata,
198 sd_bus_error *error) {
199
200
201 ExecContext *c = userdata;
202
203 assert(bus);
204 assert(reply);
205 assert(c);
206
207 return sd_bus_message_append(reply, "i", IOPRIO_PRIO_DATA(exec_context_get_effective_ioprio(c)));
82c121a4
LP
208}
209
718db961
LP
210static int property_get_cpu_sched_policy(
211 sd_bus *bus,
212 const char *path,
213 const char *interface,
214 const char *property,
215 sd_bus_message *reply,
ebcf1f97
LP
216 void *userdata,
217 sd_bus_error *error) {
718db961
LP
218
219 ExecContext *c = userdata;
82c121a4
LP
220 int32_t n;
221
718db961
LP
222 assert(bus);
223 assert(reply);
82c121a4
LP
224 assert(c);
225
226 if (c->cpu_sched_set)
227 n = c->cpu_sched_policy;
718db961 228 else {
82c121a4 229 n = sched_getscheduler(0);
718db961
LP
230 if (n < 0)
231 n = SCHED_OTHER;
232 }
82c121a4 233
718db961 234 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
235}
236
718db961
LP
237static int property_get_cpu_sched_priority(
238 sd_bus *bus,
239 const char *path,
240 const char *interface,
241 const char *property,
242 sd_bus_message *reply,
ebcf1f97
LP
243 void *userdata,
244 sd_bus_error *error) {
718db961
LP
245
246 ExecContext *c = userdata;
82c121a4
LP
247 int32_t n;
248
718db961
LP
249 assert(bus);
250 assert(reply);
82c121a4
LP
251 assert(c);
252
253 if (c->cpu_sched_set)
254 n = c->cpu_sched_priority;
255 else {
b92bea5d 256 struct sched_param p = {};
82c121a4 257
82c121a4
LP
258 if (sched_getparam(0, &p) >= 0)
259 n = p.sched_priority;
e62d8c39
ZJS
260 else
261 n = 0;
82c121a4
LP
262 }
263
718db961 264 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
265}
266
718db961
LP
267static int property_get_cpu_affinity(
268 sd_bus *bus,
269 const char *path,
270 const char *interface,
271 const char *property,
272 sd_bus_message *reply,
ebcf1f97
LP
273 void *userdata,
274 sd_bus_error *error) {
82c121a4 275
718db961 276 ExecContext *c = userdata;
82c121a4 277
718db961
LP
278 assert(bus);
279 assert(reply);
280 assert(c);
82c121a4
LP
281
282 if (c->cpuset)
718db961 283 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
82c121a4 284 else
718db961 285 return sd_bus_message_append_array(reply, 'y', NULL, 0);
82c121a4
LP
286}
287
718db961
LP
288static int property_get_timer_slack_nsec(
289 sd_bus *bus,
290 const char *path,
291 const char *interface,
292 const char *property,
293 sd_bus_message *reply,
ebcf1f97
LP
294 void *userdata,
295 sd_bus_error *error) {
718db961
LP
296
297 ExecContext *c = userdata;
82c121a4
LP
298 uint64_t u;
299
718db961
LP
300 assert(bus);
301 assert(reply);
82c121a4
LP
302 assert(c);
303
3a43da28 304 if (c->timer_slack_nsec != NSEC_INFINITY)
03fae018 305 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
306 else
307 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
308
718db961 309 return sd_bus_message_append(reply, "t", u);
82c121a4
LP
310}
311
718db961
LP
312static int property_get_capability_bounding_set(
313 sd_bus *bus,
314 const char *path,
315 const char *interface,
316 const char *property,
317 sd_bus_message *reply,
ebcf1f97
LP
318 void *userdata,
319 sd_bus_error *error) {
260abb78 320
718db961
LP
321 ExecContext *c = userdata;
322
323 assert(bus);
324 assert(reply);
260abb78
LP
325 assert(c);
326
a103496c 327 return sd_bus_message_append(reply, "t", c->capability_bounding_set);
260abb78
LP
328}
329
755d4b67
IP
330static int property_get_ambient_capabilities(
331 sd_bus *bus,
332 const char *path,
333 const char *interface,
334 const char *property,
335 sd_bus_message *reply,
336 void *userdata,
337 sd_bus_error *error) {
338
339 ExecContext *c = userdata;
340
341 assert(bus);
342 assert(reply);
343 assert(c);
344
345 return sd_bus_message_append(reply, "t", c->capability_ambient_set);
346}
347
479050b3 348static int property_get_empty_string(
718db961
LP
349 sd_bus *bus,
350 const char *path,
351 const char *interface,
352 const char *property,
353 sd_bus_message *reply,
ebcf1f97
LP
354 void *userdata,
355 sd_bus_error *error) {
718db961 356
718db961
LP
357 assert(bus);
358 assert(reply);
82c121a4 359
479050b3 360 return sd_bus_message_append(reply, "s", "");
82c121a4
LP
361}
362
718db961
LP
363static int property_get_syscall_filter(
364 sd_bus *bus,
365 const char *path,
366 const char *interface,
367 const char *property,
368 sd_bus_message *reply,
ebcf1f97
LP
369 void *userdata,
370 sd_bus_error *error) {
82c121a4 371
17df7223
LP
372 ExecContext *c = userdata;
373 _cleanup_strv_free_ char **l = NULL;
57183d11
LP
374 int r;
375
351a19b1 376#ifdef HAVE_SECCOMP
17df7223
LP
377 Iterator i;
378 void *id;
351a19b1 379#endif
17df7223
LP
380
381 assert(bus);
382 assert(reply);
383 assert(c);
384
57183d11
LP
385 r = sd_bus_message_open_container(reply, 'r', "bas");
386 if (r < 0)
387 return r;
388
389 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
390 if (r < 0)
391 return r;
392
351a19b1 393#ifdef HAVE_SECCOMP
17df7223
LP
394 SET_FOREACH(id, c->syscall_filter, i) {
395 char *name;
396
397 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
398 if (!name)
399 continue;
400
6e18964d
ZJS
401 r = strv_consume(&l, name);
402 if (r < 0)
403 return r;
17df7223 404 }
351a19b1 405#endif
17df7223
LP
406
407 strv_sort(l);
408
57183d11
LP
409 r = sd_bus_message_append_strv(reply, l);
410 if (r < 0)
411 return r;
17df7223 412
57183d11
LP
413 return sd_bus_message_close_container(reply);
414}
17df7223 415
57183d11
LP
416static int property_get_syscall_archs(
417 sd_bus *bus,
418 const char *path,
419 const char *interface,
420 const char *property,
421 sd_bus_message *reply,
422 void *userdata,
423 sd_bus_error *error) {
424
425 ExecContext *c = userdata;
426 _cleanup_strv_free_ char **l = NULL;
427 int r;
428
429#ifdef HAVE_SECCOMP
430 Iterator i;
431 void *id;
432#endif
433
434 assert(bus);
435 assert(reply);
436 assert(c);
17df7223 437
57183d11
LP
438#ifdef HAVE_SECCOMP
439 SET_FOREACH(id, c->syscall_archs, i) {
440 const char *name;
441
442 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
443 if (!name)
444 continue;
445
446 r = strv_extend(&l, name);
447 if (r < 0)
448 return -ENOMEM;
17df7223 449 }
57183d11
LP
450#endif
451
452 strv_sort(l);
453
454 r = sd_bus_message_append_strv(reply, l);
455 if (r < 0)
456 return r;
17df7223 457
57183d11 458 return 0;
17df7223
LP
459}
460
461static int property_get_syscall_errno(
462 sd_bus *bus,
463 const char *path,
464 const char *interface,
465 const char *property,
466 sd_bus_message *reply,
467 void *userdata,
468 sd_bus_error *error) {
469
718db961 470 ExecContext *c = userdata;
82c121a4 471
718db961
LP
472 assert(bus);
473 assert(reply);
474 assert(c);
82c121a4 475
17df7223 476 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
718db961 477}
82c121a4 478
5f8640fb
LP
479static int property_get_selinux_context(
480 sd_bus *bus,
481 const char *path,
482 const char *interface,
483 const char *property,
484 sd_bus_message *reply,
485 void *userdata,
486 sd_bus_error *error) {
487
488 ExecContext *c = userdata;
489
490 assert(bus);
491 assert(reply);
492 assert(c);
493
494 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
495}
496
eef65bf3
MS
497static int property_get_apparmor_profile(
498 sd_bus *bus,
499 const char *path,
500 const char *interface,
501 const char *property,
502 sd_bus_message *reply,
503 void *userdata,
504 sd_bus_error *error) {
505
506 ExecContext *c = userdata;
507
508 assert(bus);
509 assert(reply);
510 assert(c);
511
512 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
513}
514
2ca620c4
WC
515static int property_get_smack_process_label(
516 sd_bus *bus,
517 const char *path,
518 const char *interface,
519 const char *property,
520 sd_bus_message *reply,
521 void *userdata,
522 sd_bus_error *error) {
523
524 ExecContext *c = userdata;
525
526 assert(bus);
527 assert(reply);
528 assert(c);
529
530 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
531}
532
ac45f971
LP
533static int property_get_personality(
534 sd_bus *bus,
535 const char *path,
536 const char *interface,
537 const char *property,
538 sd_bus_message *reply,
539 void *userdata,
540 sd_bus_error *error) {
541
542 ExecContext *c = userdata;
543
544 assert(bus);
545 assert(reply);
546 assert(c);
547
548 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
549}
550
4298d0b5
LP
551static int property_get_address_families(
552 sd_bus *bus,
553 const char *path,
554 const char *interface,
555 const char *property,
556 sd_bus_message *reply,
557 void *userdata,
558 sd_bus_error *error) {
559
560 ExecContext *c = userdata;
561 _cleanup_strv_free_ char **l = NULL;
562 Iterator i;
563 void *af;
564 int r;
565
566 assert(bus);
567 assert(reply);
568 assert(c);
569
570 r = sd_bus_message_open_container(reply, 'r', "bas");
571 if (r < 0)
572 return r;
573
574 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
575 if (r < 0)
576 return r;
577
578 SET_FOREACH(af, c->address_families, i) {
579 const char *name;
580
581 name = af_to_name(PTR_TO_INT(af));
582 if (!name)
583 continue;
584
585 r = strv_extend(&l, name);
586 if (r < 0)
587 return -ENOMEM;
588 }
589
590 strv_sort(l);
591
592 r = sd_bus_message_append_strv(reply, l);
593 if (r < 0)
594 return r;
595
596 return sd_bus_message_close_container(reply);
597}
598
5f5d8eab
LP
599static int property_get_working_directory(
600 sd_bus *bus,
601 const char *path,
602 const char *interface,
603 const char *property,
604 sd_bus_message *reply,
605 void *userdata,
606 sd_bus_error *error) {
607
608 ExecContext *c = userdata;
609 const char *wd;
610
611 assert(bus);
612 assert(reply);
613 assert(c);
614
615 if (c->working_directory_home)
616 wd = "~";
617 else
618 wd = c->working_directory;
619
620 if (c->working_directory_missing_ok)
621 wd = strjoina("!", wd);
622
623 return sd_bus_message_append(reply, "s", wd);
624}
625
06f2ccf9
EV
626static int property_get_syslog_level(
627 sd_bus *bus,
628 const char *path,
629 const char *interface,
630 const char *property,
631 sd_bus_message *reply,
632 void *userdata,
633 sd_bus_error *error) {
634
635 ExecContext *c = userdata;
636
637 assert(bus);
638 assert(reply);
639 assert(c);
640
641 return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
642}
643
644static int property_get_syslog_facility(
645 sd_bus *bus,
646 const char *path,
647 const char *interface,
648 const char *property,
649 sd_bus_message *reply,
650 void *userdata,
651 sd_bus_error *error) {
652
653 ExecContext *c = userdata;
654
655 assert(bus);
656 assert(reply);
657 assert(c);
658
659 return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
660}
661
52c239d7
LB
662static int property_get_input_fdname(
663 sd_bus *bus,
664 const char *path,
665 const char *interface,
666 const char *property,
667 sd_bus_message *reply,
668 void *userdata,
669 sd_bus_error *error) {
670
671 ExecContext *c = userdata;
672 const char *name;
673
674 assert(bus);
675 assert(c);
676 assert(property);
677 assert(reply);
678
679 name = exec_context_fdname(c, STDIN_FILENO);
680
681 return sd_bus_message_append(reply, "s", name);
682}
683
684static int property_get_output_fdname(
685 sd_bus *bus,
686 const char *path,
687 const char *interface,
688 const char *property,
689 sd_bus_message *reply,
690 void *userdata,
691 sd_bus_error *error) {
692
693 ExecContext *c = userdata;
694 const char *name = NULL;
695
696 assert(bus);
697 assert(c);
698 assert(property);
699 assert(reply);
700
701 if (c->std_output == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardOutputFileDescriptorName"))
702 name = exec_context_fdname(c, STDOUT_FILENO);
703 else if (c->std_error == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardErrorFileDescriptorName"))
704 name = exec_context_fdname(c, STDERR_FILENO);
705
706 return sd_bus_message_append(reply, "s", name);
707}
708
d2d6c096
LP
709static int property_get_bind_paths(
710 sd_bus *bus,
711 const char *path,
712 const char *interface,
713 const char *property,
714 sd_bus_message *reply,
715 void *userdata,
716 sd_bus_error *error) {
717
718 ExecContext *c = userdata;
719 unsigned i;
720 bool ro;
721 int r;
722
723 assert(bus);
724 assert(c);
725 assert(property);
726 assert(reply);
727
728 ro = !!strstr(property, "ReadOnly");
729
730 r = sd_bus_message_open_container(reply, 'a', "(ssbt)");
731 if (r < 0)
732 return r;
733
734 for (i = 0; i < c->n_bind_mounts; i++) {
735
736 if (ro != c->bind_mounts[i].read_only)
737 continue;
738
739 r = sd_bus_message_append(
740 reply, "(ssbt)",
741 c->bind_mounts[i].source,
742 c->bind_mounts[i].destination,
743 c->bind_mounts[i].ignore_enoent,
c9b06108 744 c->bind_mounts[i].recursive ? (uint64_t) MS_REC : (uint64_t) 0);
d2d6c096
LP
745 if (r < 0)
746 return r;
747 }
748
749 return sd_bus_message_close_container(reply);
750}
751
718db961
LP
752const sd_bus_vtable bus_exec_vtable[] = {
753 SD_BUS_VTABLE_START(0),
556089dc
LP
754 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
755 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
b4c14404 756 SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 757 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 758 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 759 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 760 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 761 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 762 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 763 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 764 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 765 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 766 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 767 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 768 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 769 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 770 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 771 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 772 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 773 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 774 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 775 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 776 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 777 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 778 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 779 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 780 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 781 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 782 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 783 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 784 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 785 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 786 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 787 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 788 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 789 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
5f5d8eab 790 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 791 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
915e6d16 792 SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
793 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
794 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
7f452159
LP
795 SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST),
796 SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
797 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
798 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
799 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
800 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
801 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
802 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
803 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
52c239d7 804 SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_input_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 805 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
52c239d7 806 SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 807 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
52c239d7 808 SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
809 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
810 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
811 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
812 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
813 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
814 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
815 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
06f2ccf9
EV
816 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
817 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
818 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
819 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
755d4b67 820 SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
821 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
822 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
29206d46 823 SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
00d9ef85 824 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 825 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 826 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
2a624c36
AP
827 SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST),
828 SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST),
829 SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
830 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
831 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
7f112f50 832 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
59eeb84b 833 SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST),
502d704e 834 SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_modules), SD_BUS_VTABLE_PROPERTY_CONST),
59eeb84b 835 SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST),
d251207d
LP
836 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
837 SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
1b8689f9
LP
838 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
839 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
840 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
841 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
023a4f67 842 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
5f8640fb 843 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
eef65bf3 844 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2ca620c4 845 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
846 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
847 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
57183d11
LP
848 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
849 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
17df7223 850 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
ac45f971 851 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
4298d0b5 852 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
e66cf1a3
LP
853 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
854 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
f3e43635 855 SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
f4170c67 856 SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
6a8c2d59 857 SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
d2d6c096
LP
858 SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
859 SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
5d997827 860 SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST),
7f452159
LP
861
862 /* Obsolete/redundant properties: */
863 SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
864 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
865 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
866 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
867 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
868
718db961
LP
869 SD_BUS_VTABLE_END
870};
82c121a4 871
4d4c80d0
LP
872static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
873 int r;
874
875 assert(reply);
876 assert(c);
877
878 if (!c->path)
879 return 0;
880
881 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
882 if (r < 0)
883 return r;
884
885 r = sd_bus_message_append(reply, "s", c->path);
886 if (r < 0)
887 return r;
888
889 r = sd_bus_message_append_strv(reply, c->argv);
890 if (r < 0)
891 return r;
892
893 r = sd_bus_message_append(reply, "bttttuii",
894 c->ignore,
895 c->exec_status.start_timestamp.realtime,
896 c->exec_status.start_timestamp.monotonic,
897 c->exec_status.exit_timestamp.realtime,
898 c->exec_status.exit_timestamp.monotonic,
899 (uint32_t) c->exec_status.pid,
900 (int32_t) c->exec_status.code,
901 (int32_t) c->exec_status.status);
902 if (r < 0)
903 return r;
904
905 return sd_bus_message_close_container(reply);
906}
907
718db961
LP
908int bus_property_get_exec_command(
909 sd_bus *bus,
910 const char *path,
911 const char *interface,
912 const char *property,
913 sd_bus_message *reply,
ebcf1f97
LP
914 void *userdata,
915 sd_bus_error *ret_error) {
fe68089d 916
4d4c80d0 917 ExecCommand *c = (ExecCommand*) userdata;
718db961 918 int r;
fe68089d 919
718db961
LP
920 assert(bus);
921 assert(reply);
fe68089d 922
718db961
LP
923 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
924 if (r < 0)
925 return r;
fe68089d 926
4d4c80d0
LP
927 r = append_exec_command(reply, c);
928 if (r < 0)
929 return r;
fe68089d 930
4d4c80d0
LP
931 return sd_bus_message_close_container(reply);
932}
718db961 933
4d4c80d0
LP
934int bus_property_get_exec_command_list(
935 sd_bus *bus,
936 const char *path,
937 const char *interface,
938 const char *property,
939 sd_bus_message *reply,
940 void *userdata,
941 sd_bus_error *ret_error) {
718db961 942
4d4c80d0
LP
943 ExecCommand *c = *(ExecCommand**) userdata;
944 int r;
718db961 945
4d4c80d0
LP
946 assert(bus);
947 assert(reply);
948
949 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
950 if (r < 0)
951 return r;
718db961 952
4d4c80d0
LP
953 LIST_FOREACH(command, c, c) {
954 r = append_exec_command(reply, c);
718db961
LP
955 if (r < 0)
956 return r;
fe68089d
LP
957 }
958
718db961 959 return sd_bus_message_close_container(reply);
8351ceae 960}
c7040b5d
LP
961
962int bus_exec_context_set_transient_property(
963 Unit *u,
964 ExecContext *c,
965 const char *name,
966 sd_bus_message *message,
967 UnitSetPropertiesMode mode,
968 sd_bus_error *error) {
969
cab2aca3
LP
970 const char *soft = NULL;
971 int r, ri;
c7040b5d
LP
972
973 assert(u);
974 assert(c);
975 assert(name);
976 assert(message);
977
978 if (streq(name, "User")) {
979 const char *uu;
980
981 r = sd_bus_message_read(message, "s", &uu);
982 if (r < 0)
983 return r;
984
6f3e7985
LP
985 if (!isempty(uu) && !valid_user_group_name_or_id(uu))
986 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user name: %s", uu);
987
c7040b5d 988 if (mode != UNIT_CHECK) {
76736280
LP
989
990 if (isempty(uu))
991 c->user = mfree(c->user);
992 else if (free_and_strdup(&c->user, uu) < 0)
993 return -ENOMEM;
c7040b5d 994
b27b4b51 995 unit_write_drop_in_private_format(u, mode, name, "User=%s", uu);
c7040b5d
LP
996 }
997
998 return 1;
999
1000 } else if (streq(name, "Group")) {
1001 const char *gg;
1002
1003 r = sd_bus_message_read(message, "s", &gg);
1004 if (r < 0)
1005 return r;
1006
6f3e7985
LP
1007 if (!isempty(gg) && !valid_user_group_name_or_id(gg))
1008 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group name: %s", gg);
1009
c7040b5d 1010 if (mode != UNIT_CHECK) {
76736280
LP
1011
1012 if (isempty(gg))
1013 c->group = mfree(c->group);
1014 else if (free_and_strdup(&c->group, gg) < 0)
1015 return -ENOMEM;
c7040b5d 1016
b27b4b51 1017 unit_write_drop_in_private_format(u, mode, name, "Group=%s", gg);
c7040b5d
LP
1018 }
1019
1020 return 1;
de53c417
EV
1021 } else if (streq(name, "SyslogIdentifier")) {
1022 const char *id;
c7040b5d 1023
de53c417
EV
1024 r = sd_bus_message_read(message, "s", &id);
1025 if (r < 0)
1026 return r;
1027
1028 if (mode != UNIT_CHECK) {
76736280
LP
1029
1030 if (isempty(id))
1031 c->syslog_identifier = mfree(c->syslog_identifier);
1032 else if (free_and_strdup(&c->syslog_identifier, id) < 0)
1033 return -ENOMEM;
de53c417 1034
b27b4b51 1035 unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s", id);
de53c417
EV
1036 }
1037
a8a13575
EV
1038 return 1;
1039 } else if (streq(name, "SyslogLevel")) {
1040 int level;
1041
1042 r = sd_bus_message_read(message, "i", &level);
1043 if (r < 0)
1044 return r;
1045
e0d6e0fa
EV
1046 if (!log_level_is_valid(level))
1047 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
1048
a8a13575
EV
1049 if (mode != UNIT_CHECK) {
1050 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
b27b4b51 1051 unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i", level);
a8a13575
EV
1052 }
1053
460ed929
EV
1054 return 1;
1055 } else if (streq(name, "SyslogFacility")) {
1056 int facility;
1057
1058 r = sd_bus_message_read(message, "i", &facility);
1059 if (r < 0)
1060 return r;
1061
e0d6e0fa
EV
1062 if (!log_facility_unshifted_is_valid(facility))
1063 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
1064
460ed929
EV
1065 if (mode != UNIT_CHECK) {
1066 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
b27b4b51 1067 unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i", facility);
460ed929
EV
1068 }
1069
de53c417 1070 return 1;
c7040b5d
LP
1071 } else if (streq(name, "Nice")) {
1072 int n;
1073
1074 r = sd_bus_message_read(message, "i", &n);
1075 if (r < 0)
1076 return r;
1077
41bf0590 1078 if (!nice_is_valid(n))
c7040b5d
LP
1079 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
1080
1081 if (mode != UNIT_CHECK) {
1082 c->nice = n;
b27b4b51 1083 unit_write_drop_in_private_format(u, mode, name, "Nice=%i", n);
c7040b5d
LP
1084 }
1085
1086 return 1;
1087
7f452159
LP
1088 } else if (streq(name, "IOSchedulingClass")) {
1089 int32_t q;
1090
1091 r = sd_bus_message_read(message, "i", &q);
1092 if (r < 0)
1093 return r;
1094
1095 if (!ioprio_class_is_valid(q))
1096 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q);
1097
1098 if (mode != UNIT_CHECK) {
1099 _cleanup_free_ char *s = NULL;
1100
1101 r = ioprio_class_to_string_alloc(q, &s);
1102 if (r < 0)
1103 return r;
1104
1105 c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio));
1106 c->ioprio_set = true;
1107
1108 unit_write_drop_in_private_format(u, mode, name, "IOSchedulingClass=%s", s);
1109 }
1110
1111 return 1;
1112
1113 } else if (streq(name, "IOSchedulingPriority")) {
1114 int32_t p;
1115
1116 r = sd_bus_message_read(message, "i", &p);
1117 if (r < 0)
1118 return r;
1119
1120 if (!ioprio_priority_is_valid(p))
1121 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
1122
1123 if (mode != UNIT_CHECK) {
1124 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p);
1125 c->ioprio_set = true;
1126
1127 unit_write_drop_in_private_format(u, mode, name, "IOSchedulingPriority=%i", p);
1128 }
1129
1130 return 1;
1131
915e6d16 1132 } else if (STR_IN_SET(name, "TTYPath", "RootDirectory", "RootImage")) {
602b8355 1133 const char *s;
9b15b784 1134
602b8355 1135 r = sd_bus_message_read(message, "s", &s);
9b15b784
LP
1136 if (r < 0)
1137 return r;
1138
602b8355
NC
1139 if (!path_is_absolute(s))
1140 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
9b15b784
LP
1141
1142 if (mode != UNIT_CHECK) {
5f5d8eab
LP
1143 if (streq(name, "TTYPath"))
1144 r = free_and_strdup(&c->tty_path, s);
915e6d16
LP
1145 else if (streq(name, "RootImage"))
1146 r = free_and_strdup(&c->root_image, s);
5f5d8eab
LP
1147 else {
1148 assert(streq(name, "RootDirectory"));
1149 r = free_and_strdup(&c->root_directory, s);
602b8355 1150 }
5f5d8eab
LP
1151 if (r < 0)
1152 return r;
9b15b784 1153
b27b4b51 1154 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
9b15b784
LP
1155 }
1156
1157 return 1;
1158
5f5d8eab
LP
1159 } else if (streq(name, "WorkingDirectory")) {
1160 const char *s;
1161 bool missing_ok;
1162
1163 r = sd_bus_message_read(message, "s", &s);
1164 if (r < 0)
1165 return r;
1166
1167 if (s[0] == '-') {
1168 missing_ok = true;
1169 s++;
1170 } else
1171 missing_ok = false;
1172
1173 if (!streq(s, "~") && !path_is_absolute(s))
1174 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
1175
1176 if (mode != UNIT_CHECK) {
1177 if (streq(s, "~")) {
1178 c->working_directory = mfree(c->working_directory);
1179 c->working_directory_home = true;
1180 } else {
1181 r = free_and_strdup(&c->working_directory, s);
1182 if (r < 0)
1183 return r;
1184
1185 c->working_directory_home = false;
1186 }
1187
1188 c->working_directory_missing_ok = missing_ok;
b27b4b51 1189 unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
5f5d8eab
LP
1190 }
1191
1192 return 1;
1193
9b15b784
LP
1194 } else if (streq(name, "StandardInput")) {
1195 const char *s;
1196 ExecInput p;
1197
1198 r = sd_bus_message_read(message, "s", &s);
1199 if (r < 0)
1200 return r;
1201
1202 p = exec_input_from_string(s);
1203 if (p < 0)
1204 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
1205
1206 if (mode != UNIT_CHECK) {
1207 c->std_input = p;
1208
b27b4b51 1209 unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s", exec_input_to_string(p));
9b15b784
LP
1210 }
1211
1212 return 1;
1213
9b15b784
LP
1214 } else if (streq(name, "StandardOutput")) {
1215 const char *s;
1216 ExecOutput p;
1217
1218 r = sd_bus_message_read(message, "s", &s);
1219 if (r < 0)
1220 return r;
1221
1222 p = exec_output_from_string(s);
1223 if (p < 0)
1224 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
1225
1226 if (mode != UNIT_CHECK) {
1227 c->std_output = p;
1228
b27b4b51 1229 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s", exec_output_to_string(p));
9b15b784
LP
1230 }
1231
1232 return 1;
1233
1234 } else if (streq(name, "StandardError")) {
1235 const char *s;
1236 ExecOutput p;
1237
1238 r = sd_bus_message_read(message, "s", &s);
1239 if (r < 0)
1240 return r;
1241
1242 p = exec_output_from_string(s);
1243 if (p < 0)
1244 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
1245
1246 if (mode != UNIT_CHECK) {
1247 c->std_error = p;
1248
b27b4b51 1249 unit_write_drop_in_private_format(u, mode, name, "StandardError=%s", exec_output_to_string(p));
9b15b784
LP
1250 }
1251
1252 return 1;
1253
52c239d7
LB
1254 } else if (STR_IN_SET(name,
1255 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
1256 const char *s;
1257
1258 r = sd_bus_message_read(message, "s", &s);
1259 if (r < 0)
1260 return r;
1261
1262 if (!fdname_is_valid(s))
1263 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
1264
1265 if (mode != UNIT_CHECK) {
1266 if (streq(name, "StandardInputFileDescriptorName")) {
1267 c->std_input = EXEC_INPUT_NAMED_FD;
1268 r = free_and_strdup(&c->stdio_fdname[STDIN_FILENO], s);
1269 if (r < 0)
1270 return r;
1271 unit_write_drop_in_private_format(u, mode, name, "StandardInput=fd:%s", s);
1272 } else if (streq(name, "StandardOutputFileDescriptorName")) {
1273 c->std_output = EXEC_OUTPUT_NAMED_FD;
1274 r = free_and_strdup(&c->stdio_fdname[STDOUT_FILENO], s);
1275 if (r < 0)
1276 return r;
1277 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=fd:%s", s);
1278 } else if (streq(name, "StandardErrorFileDescriptorName")) {
1279 c->std_error = EXEC_OUTPUT_NAMED_FD;
1280 r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], s);
1281 if (r < 0)
1282 return r;
1283 unit_write_drop_in_private_format(u, mode, name, "StandardError=fd:%s", s);
1284 }
1285 }
1286
1287 return 1;
1288
b9c50073
GP
1289 } else if (STR_IN_SET(name,
1290 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
d251207d 1291 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers",
29206d46 1292 "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute",
59eeb84b 1293 "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables",
5d997827 1294 "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS")) {
506711fd
LP
1295 int b;
1296
1297 r = sd_bus_message_read(message, "b", &b);
1298 if (r < 0)
1299 return r;
1300
1301 if (mode != UNIT_CHECK) {
b9c50073
GP
1302 if (streq(name, "IgnoreSIGPIPE"))
1303 c->ignore_sigpipe = b;
1304 else if (streq(name, "TTYVHangup"))
1305 c->tty_vhangup = b;
1306 else if (streq(name, "TTYReset"))
1307 c->tty_reset = b;
1308 else if (streq(name, "PrivateTmp"))
1309 c->private_tmp = b;
1310 else if (streq(name, "PrivateDevices"))
1311 c->private_devices = b;
1312 else if (streq(name, "PrivateNetwork"))
1313 c->private_network = b;
d251207d
LP
1314 else if (streq(name, "PrivateUsers"))
1315 c->private_users = b;
b9c50073
GP
1316 else if (streq(name, "NoNewPrivileges"))
1317 c->no_new_privileges = b;
047d9933
EV
1318 else if (streq(name, "SyslogLevelPrefix"))
1319 c->syslog_level_prefix = b;
f3e43635
TM
1320 else if (streq(name, "MemoryDenyWriteExecute"))
1321 c->memory_deny_write_execute = b;
f4170c67
LP
1322 else if (streq(name, "RestrictRealtime"))
1323 c->restrict_realtime = b;
29206d46
LP
1324 else if (streq(name, "DynamicUser"))
1325 c->dynamic_user = b;
00d9ef85
LP
1326 else if (streq(name, "RemoveIPC"))
1327 c->remove_ipc = b;
59eeb84b
LP
1328 else if (streq(name, "ProtectKernelTunables"))
1329 c->protect_kernel_tunables = b;
502d704e
DH
1330 else if (streq(name, "ProtectKernelModules"))
1331 c->protect_kernel_modules = b;
59eeb84b
LP
1332 else if (streq(name, "ProtectControlGroups"))
1333 c->protect_control_groups = b;
5d997827
LP
1334 else if (streq(name, "MountAPIVFS"))
1335 c->mount_apivfs = b;
b9c50073 1336
b27b4b51 1337 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, yes_no(b));
506711fd
LP
1338 }
1339
1340 return 1;
1341
1342 } else if (streq(name, "UtmpIdentifier")) {
1343 const char *id;
1344
1345 r = sd_bus_message_read(message, "s", &id);
1346 if (r < 0)
1347 return r;
1348
1349 if (mode != UNIT_CHECK) {
76736280
LP
1350 if (isempty(id))
1351 c->utmp_id = mfree(c->utmp_id);
1352 else if (free_and_strdup(&c->utmp_id, id) < 0)
1353 return -ENOMEM;
506711fd 1354
b27b4b51 1355 unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s", strempty(id));
506711fd
LP
1356 }
1357
1358 return 1;
1359
1360 } else if (streq(name, "UtmpMode")) {
1361 const char *s;
1362 ExecUtmpMode m;
1363
1364 r = sd_bus_message_read(message, "s", &s);
1365 if (r < 0)
1366 return r;
1367
1368 m = exec_utmp_mode_from_string(s);
1369 if (m < 0)
1370 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
1371
1372 if (mode != UNIT_CHECK) {
1373 c->utmp_mode = m;
1374
b27b4b51 1375 unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s", exec_utmp_mode_to_string(m));
506711fd
LP
1376 }
1377
1378 return 1;
1379
1380 } else if (streq(name, "PAMName")) {
1381 const char *n;
1382
1383 r = sd_bus_message_read(message, "s", &n);
1384 if (r < 0)
1385 return r;
1386
1387 if (mode != UNIT_CHECK) {
76736280
LP
1388 if (isempty(n))
1389 c->pam_name = mfree(c->pam_name);
1390 else if (free_and_strdup(&c->pam_name, n) < 0)
1391 return -ENOMEM;
506711fd 1392
b27b4b51 1393 unit_write_drop_in_private_format(u, mode, name, "PAMName=%s", strempty(n));
506711fd
LP
1394 }
1395
1396 return 1;
1397
c7040b5d
LP
1398 } else if (streq(name, "Environment")) {
1399
f900f582 1400 _cleanup_strv_free_ char **l = NULL, **q = NULL;
c7040b5d
LP
1401
1402 r = sd_bus_message_read_strv(message, &l);
1403 if (r < 0)
1404 return r;
1405
1406 if (!strv_env_is_valid(l))
1407 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1408
f900f582
ZJS
1409 r = unit_full_printf_strv(u, l, &q);
1410 if (r < 0)
1411 return r;
c7040b5d 1412
f900f582
ZJS
1413 if (mode != UNIT_CHECK) {
1414 if (strv_length(q) == 0) {
e9876fc9 1415 c->environment = strv_free(c->environment);
b27b4b51 1416 unit_write_drop_in_private_format(u, mode, name, "Environment=");
e9876fc9 1417 } else {
f900f582
ZJS
1418 _cleanup_free_ char *joined = NULL;
1419 char **e;
1420
1421 e = strv_env_merge(2, c->environment, q);
e9876fc9
EV
1422 if (!e)
1423 return -ENOMEM;
c7040b5d 1424
e9876fc9
EV
1425 strv_free(c->environment);
1426 c->environment = e;
c7040b5d 1427
f900f582
ZJS
1428 /* We write just the new settings out to file, with unresolved specifiers */
1429 joined = strv_join_quoted(q);
e9876fc9
EV
1430 if (!joined)
1431 return -ENOMEM;
1432
b27b4b51 1433 unit_write_drop_in_private_format(u, mode, name, "Environment=%s", joined);
e9876fc9 1434 }
c7040b5d
LP
1435 }
1436
d584f638
LP
1437 return 1;
1438
f1db3327
EV
1439 } else if (streq(name, "TimerSlackNSec")) {
1440
1441 nsec_t n;
1442
1443 r = sd_bus_message_read(message, "t", &n);
1444 if (r < 0)
1445 return r;
1446
1447 if (mode != UNIT_CHECK) {
1448 c->timer_slack_nsec = n;
b27b4b51 1449 unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT, n);
f1db3327
EV
1450 }
1451
1452 return 1;
1453
6b862936
EV
1454 } else if (streq(name, "OOMScoreAdjust")) {
1455 int oa;
1456
1457 r = sd_bus_message_read(message, "i", &oa);
1458 if (r < 0)
1459 return r;
1460
1461 if (!oom_score_adjust_is_valid(oa))
1462 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
1463
1464 if (mode != UNIT_CHECK) {
1465 c->oom_score_adjust = oa;
1466 c->oom_score_adjust_set = true;
b27b4b51 1467 unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i", oa);
6b862936
EV
1468 }
1469
1470 return 1;
1471
ceb728cf
NC
1472 } else if (streq(name, "EnvironmentFiles")) {
1473
1474 _cleanup_free_ char *joined = NULL;
1475 _cleanup_fclose_ FILE *f = NULL;
9b531f04 1476 _cleanup_strv_free_ char **l = NULL;
ceb728cf 1477 size_t size = 0;
2229f656 1478 char **i;
ceb728cf
NC
1479
1480 r = sd_bus_message_enter_container(message, 'a', "(sb)");
1481 if (r < 0)
1482 return r;
1483
1484 f = open_memstream(&joined, &size);
1485 if (!f)
1486 return -ENOMEM;
1487
2229f656 1488 STRV_FOREACH(i, c->environment_files)
b27b4b51 1489 fprintf(f, "EnvironmentFile=%s", *i);
ceb728cf
NC
1490
1491 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
1492 const char *path;
1493 int b;
1494
ceb728cf
NC
1495 r = sd_bus_message_read(message, "sb", &path, &b);
1496 if (r < 0)
1497 return r;
1498
1499 r = sd_bus_message_exit_container(message);
1500 if (r < 0)
1501 return r;
1502
d2d6c096
LP
1503 if (!path_is_absolute(path))
1504 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
ceb728cf
NC
1505
1506 if (mode != UNIT_CHECK) {
ceb728cf
NC
1507 char *buf = NULL;
1508
605405c6 1509 buf = strjoin(b ? "-" : "", path);
2229f656 1510 if (!buf)
ceb728cf
NC
1511 return -ENOMEM;
1512
b27b4b51 1513 fprintf(f, "EnvironmentFile=%s", buf);
ceb728cf 1514
2229f656 1515 r = strv_consume(&l, buf);
ceb728cf
NC
1516 if (r < 0)
1517 return r;
1518 }
1519 }
1520 if (r < 0)
1521 return r;
1522
b0830e21
LP
1523 r = sd_bus_message_exit_container(message);
1524 if (r < 0)
1525 return r;
1526
2229f656
LP
1527 r = fflush_and_check(f);
1528 if (r < 0)
1529 return r;
ceb728cf 1530
2229f656
LP
1531 if (mode != UNIT_CHECK) {
1532 if (strv_isempty(l)) {
1533 c->environment_files = strv_free(c->environment_files);
b27b4b51 1534 unit_write_drop_in_private(u, mode, name, "EnvironmentFile=");
2229f656
LP
1535 } else {
1536 r = strv_extend_strv(&c->environment_files, l, true);
1537 if (r < 0)
1538 return r;
1539
ceb728cf 1540 unit_write_drop_in_private(u, mode, name, joined);
2229f656
LP
1541 }
1542 }
ceb728cf 1543
ceb728cf
NC
1544 return 1;
1545
b4c14404
FB
1546 } else if (streq(name, "PassEnvironment")) {
1547
1548 _cleanup_strv_free_ char **l = NULL;
1549
1550 r = sd_bus_message_read_strv(message, &l);
1551 if (r < 0)
1552 return r;
1553
1554 if (!strv_env_name_is_valid(l))
1555 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment block.");
1556
1557 if (mode != UNIT_CHECK) {
1558 if (strv_isempty(l)) {
1559 c->pass_environment = strv_free(c->pass_environment);
b27b4b51 1560 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=");
b4c14404
FB
1561 } else {
1562 _cleanup_free_ char *joined = NULL;
1563
1564 r = strv_extend_strv(&c->pass_environment, l, true);
1565 if (r < 0)
1566 return r;
1567
1568 joined = strv_join_quoted(c->pass_environment);
1569 if (!joined)
1570 return -ENOMEM;
1571
b27b4b51 1572 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=%s", joined);
b4c14404
FB
1573 }
1574 }
1575
1576 return 1;
1577
2a624c36
AP
1578 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
1579 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) {
08596068
EV
1580 _cleanup_strv_free_ char **l = NULL;
1581 char ***dirs;
1582 char **p;
1583
1584 r = sd_bus_message_read_strv(message, &l);
1585 if (r < 0)
1586 return r;
1587
1588 STRV_FOREACH(p, l) {
20b7a007
LP
1589 const char *i = *p;
1590 size_t offset;
1591
1592 if (!utf8_is_valid(i))
08596068
EV
1593 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1594
20b7a007
LP
1595 offset = i[0] == '-';
1596 offset += i[offset] == '+';
1597 if (!path_is_absolute(i + offset))
08596068
EV
1598 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1599 }
1600
1601 if (mode != UNIT_CHECK) {
1602 _cleanup_free_ char *joined = NULL;
1603
c4b41707
AP
1604 if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths"))
1605 dirs = &c->read_write_paths;
1606 else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
1607 dirs = &c->read_only_paths;
1608 else /* "InaccessiblePaths" */
1609 dirs = &c->inaccessible_paths;
08596068
EV
1610
1611 if (strv_length(l) == 0) {
1612 *dirs = strv_free(*dirs);
b27b4b51 1613 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
08596068
EV
1614 } else {
1615 r = strv_extend_strv(dirs, l, true);
08596068
EV
1616 if (r < 0)
1617 return -ENOMEM;
1618
1619 joined = strv_join_quoted(*dirs);
1620 if (!joined)
1621 return -ENOMEM;
1622
b27b4b51 1623 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
08596068
EV
1624 }
1625
1626 }
1627
1628 return 1;
1629
5664e6cf
EV
1630 } else if (streq(name, "ProtectSystem")) {
1631 const char *s;
1632 ProtectSystem ps;
1633
1634 r = sd_bus_message_read(message, "s", &s);
1635 if (r < 0)
1636 return r;
1637
1638 r = parse_boolean(s);
1639 if (r > 0)
1640 ps = PROTECT_SYSTEM_YES;
1641 else if (r == 0)
1642 ps = PROTECT_SYSTEM_NO;
1643 else {
1644 ps = protect_system_from_string(s);
1645 if (ps < 0)
1646 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value");
1647 }
1648
1649 if (mode != UNIT_CHECK) {
1650 c->protect_system = ps;
b27b4b51 1651 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
5664e6cf
EV
1652 }
1653
1654 return 1;
1655
eff58074
EV
1656 } else if (streq(name, "ProtectHome")) {
1657 const char *s;
1658 ProtectHome ph;
1659
1660 r = sd_bus_message_read(message, "s", &s);
1661 if (r < 0)
1662 return r;
1663
1664 r = parse_boolean(s);
1665 if (r > 0)
1666 ph = PROTECT_HOME_YES;
1667 else if (r == 0)
1668 ph = PROTECT_HOME_NO;
1669 else {
1670 ph = protect_home_from_string(s);
1671 if (ph < 0)
1672 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value");
1673 }
1674
1675 if (mode != UNIT_CHECK) {
1676 c->protect_home = ph;
b27b4b51 1677 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
eff58074
EV
1678 }
1679
1680 return 1;
1681
fa21b5e3
EV
1682 } else if (streq(name, "RuntimeDirectory")) {
1683 _cleanup_strv_free_ char **l = NULL;
1684 char **p;
1685
1686 r = sd_bus_message_read_strv(message, &l);
1687 if (r < 0)
1688 return r;
1689
1690 STRV_FOREACH(p, l) {
1691 if (!filename_is_valid(*p))
1692 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Runtime directory is not valid %s", *p);
1693 }
1694
1695 if (mode != UNIT_CHECK) {
1696 _cleanup_free_ char *joined = NULL;
1697
1698 if (strv_isempty(l)) {
1699 c->runtime_directory = strv_free(c->runtime_directory);
b27b4b51 1700 unit_write_drop_in_private_format(u, mode, name, "%s=", name);
fa21b5e3
EV
1701 } else {
1702 r = strv_extend_strv(&c->runtime_directory, l, true);
1703
1704 if (r < 0)
1705 return -ENOMEM;
1706
1707 joined = strv_join_quoted(c->runtime_directory);
1708 if (!joined)
1709 return -ENOMEM;
1710
b27b4b51 1711 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
fa21b5e3
EV
1712 }
1713 }
1714
1715 return 1;
1716
186ad4b1
JB
1717 } else if (streq(name, "SELinuxContext")) {
1718 const char *s;
1719
1720 r = sd_bus_message_read(message, "s", &s);
1721 if (r < 0)
1722 return r;
1723
1724 if (mode != UNIT_CHECK) {
4e282d11
JB
1725 if (isempty(s))
1726 c->selinux_context = mfree(c->selinux_context);
1727 else if (free_and_strdup(&c->selinux_context, s) < 0)
1728 return -ENOMEM;
186ad4b1 1729
b27b4b51 1730 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, strempty(s));
186ad4b1
JB
1731 }
1732
1733 return 1;
add00535
LP
1734 } else if (streq(name, "RestrictNamespaces")) {
1735 uint64_t flags;
186ad4b1 1736
add00535
LP
1737 r = sd_bus_message_read(message, "t", &flags);
1738 if (r < 0)
1739 return r;
1740 if ((flags & NAMESPACE_FLAGS_ALL) != flags)
1741 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown namespace types");
1742
1743 if (mode != UNIT_CHECK) {
1744 _cleanup_free_ char *s = NULL;
1745
1746 r = namespace_flag_to_string_many(flags, &s);
1747 if (r < 0)
1748 return r;
1749
1750 c->restrict_namespaces = flags;
1751 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
1752 }
1753
1754 return 1;
83555251
LP
1755 } else if (streq(name, "MountFlags")) {
1756 uint64_t flags;
1757
1758 r = sd_bus_message_read(message, "t", &flags);
1759 if (r < 0)
1760 return r;
1761 if (!IN_SET(flags, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
1762 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount propagation flags");
cab2aca3 1763
83555251
LP
1764 if (mode != UNIT_CHECK) {
1765 c->mount_flags = flags;
1766
c7383828 1767 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, mount_propagation_flags_to_string(flags));
83555251
LP
1768 }
1769
d2d6c096
LP
1770 return 1;
1771 } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
1772 unsigned empty = true;
1773
1774 r = sd_bus_message_enter_container(message, 'a', "(ssbt)");
1775 if (r < 0)
1776 return r;
1777
1778 while ((r = sd_bus_message_enter_container(message, 'r', "ssbt")) > 0) {
1779 const char *source, *destination;
1780 int ignore_enoent;
1781 uint64_t mount_flags;
1782
1783 r = sd_bus_message_read(message, "ssbt", &source, &destination, &ignore_enoent, &mount_flags);
1784 if (r < 0)
1785 return r;
1786
1787 r = sd_bus_message_exit_container(message);
1788 if (r < 0)
1789 return r;
1790
1791 if (!path_is_absolute(source))
1792 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
1793 if (!path_is_absolute(destination))
91d910e3 1794 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
d2d6c096
LP
1795 if (!IN_SET(mount_flags, 0, MS_REC))
1796 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
1797
1798 if (mode != UNIT_CHECK) {
1799 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
1800 &(BindMount) {
1801 .source = strdup(source),
1802 .destination = strdup(destination),
1803 .read_only = !!strstr(name, "ReadOnly"),
1804 .recursive = !!(mount_flags & MS_REC),
1805 .ignore_enoent = ignore_enoent,
1806 });
1807 if (r < 0)
1808 return r;
1809
1810 unit_write_drop_in_private_format(
1811 u, mode, name,
1812 "%s=%s%s:%s:%s",
1813 name,
1814 ignore_enoent ? "-" : "",
1815 source,
1816 destination,
1817 (mount_flags & MS_REC) ? "rbind" : "norbind");
1818 }
1819
1820 empty = false;
1821 }
1822 if (r < 0)
1823 return r;
1824
1825 r = sd_bus_message_exit_container(message);
1826 if (r < 0)
1827 return r;
1828
1829 if (empty) {
1830 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
1831 c->bind_mounts = NULL;
1832 c->n_bind_mounts = 0;
1833 }
1834
83555251
LP
1835 return 1;
1836 }
d2d6c096 1837
cab2aca3
LP
1838 ri = rlimit_from_string(name);
1839 if (ri < 0) {
1840 soft = endswith(name, "Soft");
1841 if (soft) {
1842 const char *n;
1843
1844 n = strndupa(name, soft - name);
1845 ri = rlimit_from_string(n);
1846 if (ri >= 0)
1847 name = n;
1848
1849 }
1850 }
1851
1852 if (ri >= 0) {
d584f638
LP
1853 uint64_t rl;
1854 rlim_t x;
1855
1856 r = sd_bus_message_read(message, "t", &rl);
1857 if (r < 0)
1858 return r;
1859
1860 if (rl == (uint64_t) -1)
1861 x = RLIM_INFINITY;
1862 else {
1863 x = (rlim_t) rl;
1864
1865 if ((uint64_t) x != rl)
1866 return -ERANGE;
1867 }
1868
1869 if (mode != UNIT_CHECK) {
cab2aca3
LP
1870 _cleanup_free_ char *f = NULL;
1871 struct rlimit nl;
1872
1873 if (c->rlimit[ri]) {
1874 nl = *c->rlimit[ri];
1875
1876 if (soft)
1877 nl.rlim_cur = x;
1878 else
1879 nl.rlim_max = x;
1880 } else
1881 /* When the resource limit is not initialized yet, then assign the value to both fields */
1882 nl = (struct rlimit) {
1883 .rlim_cur = x,
1884 .rlim_max = x,
1885 };
1886
1887 r = rlimit_format(&nl, &f);
1888 if (r < 0)
1889 return r;
d584f638 1890
cab2aca3
LP
1891 if (c->rlimit[ri])
1892 *c->rlimit[ri] = nl;
1893 else {
1894 c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
1895 if (!c->rlimit[ri])
d584f638
LP
1896 return -ENOMEM;
1897 }
1898
b27b4b51 1899 unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, f);
d584f638
LP
1900 }
1901
c7040b5d
LP
1902 return 1;
1903 }
1904
1905 return 0;
1906}