]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
detect-virt: add new --chroot switch to detect chroot() environments
[thirdparty/systemd.git] / src / core / dbus-execute.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4139c1b2
LP
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
4139c1b2
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
4139c1b2 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
4139c1b2
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
82c121a4 22#include <sys/prctl.h>
4139c1b2 23
57183d11
LP
24#ifdef HAVE_SECCOMP
25#include <seccomp.h>
26#endif
27
3ffd4af2 28#include "af-list.h"
718db961 29#include "bus-util.h"
430f0182 30#include "capability-util.h"
3ffd4af2 31#include "dbus-execute.h"
c7040b5d 32#include "env-util.h"
3ffd4af2
LP
33#include "execute.h"
34#include "fd-util.h"
35#include "fileio.h"
36#include "ioprio.h"
37#include "missing.h"
417116f2 38#include "namespace.h"
6bedfcbb 39#include "parse-util.h"
9b15b784 40#include "path-util.h"
78f22b97 41#include "rlimit-util.h"
57183d11
LP
42#ifdef HAVE_SECCOMP
43#include "seccomp-util.h"
44#endif
6bedfcbb
LP
45#include "strv.h"
46#include "utf8.h"
57183d11 47
718db961 48BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
82c121a4 49
718db961 50static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
8c7be95e 51
023a4f67
LP
52static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
53
1b8689f9
LP
54static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
55static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
417116f2 56
718db961
LP
57static int property_get_environment_files(
58 sd_bus *bus,
59 const char *path,
60 const char *interface,
61 const char *property,
62 sd_bus_message *reply,
ebcf1f97
LP
63 void *userdata,
64 sd_bus_error *error) {
8c7be95e 65
718db961
LP
66 ExecContext *c = userdata;
67 char **j;
68 int r;
8c7be95e 69
718db961
LP
70 assert(bus);
71 assert(reply);
72 assert(c);
73
74 r = sd_bus_message_open_container(reply, 'a', "(sb)");
75 if (r < 0)
76 return r;
8c7be95e 77
718db961
LP
78 STRV_FOREACH(j, c->environment_files) {
79 const char *fn = *j;
8c7be95e 80
718db961
LP
81 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
82 if (r < 0)
83 return r;
8c7be95e
LP
84 }
85
718db961
LP
86 return sd_bus_message_close_container(reply);
87}
88
718db961
LP
89static int property_get_oom_score_adjust(
90 sd_bus *bus,
91 const char *path,
92 const char *interface,
93 const char *property,
94 sd_bus_message *reply,
ebcf1f97
LP
95 void *userdata,
96 sd_bus_error *error) {
718db961
LP
97
98
99 ExecContext *c = userdata;
82c121a4
LP
100 int32_t n;
101
718db961
LP
102 assert(bus);
103 assert(reply);
82c121a4
LP
104 assert(c);
105
dd6c17b1
LP
106 if (c->oom_score_adjust_set)
107 n = c->oom_score_adjust;
82c121a4 108 else {
68eda4bd 109 _cleanup_free_ char *t = NULL;
82c121a4
LP
110
111 n = 0;
718db961 112 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
e4e73a63 113 safe_atoi32(t, &n);
82c121a4
LP
114 }
115
718db961 116 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
117}
118
718db961
LP
119static int property_get_nice(
120 sd_bus *bus,
121 const char *path,
122 const char *interface,
123 const char *property,
124 sd_bus_message *reply,
ebcf1f97
LP
125 void *userdata,
126 sd_bus_error *error) {
718db961
LP
127
128
129 ExecContext *c = userdata;
82c121a4
LP
130 int32_t n;
131
718db961
LP
132 assert(bus);
133 assert(reply);
82c121a4
LP
134 assert(c);
135
136 if (c->nice_set)
137 n = c->nice;
718db961
LP
138 else {
139 errno = 0;
82c121a4 140 n = getpriority(PRIO_PROCESS, 0);
718db961
LP
141 if (errno != 0)
142 n = 0;
143 }
82c121a4 144
718db961 145 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
146}
147
718db961
LP
148static int property_get_ioprio(
149 sd_bus *bus,
150 const char *path,
151 const char *interface,
152 const char *property,
153 sd_bus_message *reply,
ebcf1f97
LP
154 void *userdata,
155 sd_bus_error *error) {
718db961
LP
156
157
158 ExecContext *c = userdata;
82c121a4
LP
159 int32_t n;
160
718db961
LP
161 assert(bus);
162 assert(reply);
82c121a4
LP
163 assert(c);
164
165 if (c->ioprio_set)
166 n = c->ioprio;
718db961 167 else {
82c121a4 168 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
718db961
LP
169 if (n < 0)
170 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
171 }
82c121a4 172
718db961 173 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
174}
175
718db961
LP
176static int property_get_cpu_sched_policy(
177 sd_bus *bus,
178 const char *path,
179 const char *interface,
180 const char *property,
181 sd_bus_message *reply,
ebcf1f97
LP
182 void *userdata,
183 sd_bus_error *error) {
718db961
LP
184
185 ExecContext *c = userdata;
82c121a4
LP
186 int32_t n;
187
718db961
LP
188 assert(bus);
189 assert(reply);
82c121a4
LP
190 assert(c);
191
192 if (c->cpu_sched_set)
193 n = c->cpu_sched_policy;
718db961 194 else {
82c121a4 195 n = sched_getscheduler(0);
718db961
LP
196 if (n < 0)
197 n = SCHED_OTHER;
198 }
82c121a4 199
718db961 200 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
201}
202
718db961
LP
203static int property_get_cpu_sched_priority(
204 sd_bus *bus,
205 const char *path,
206 const char *interface,
207 const char *property,
208 sd_bus_message *reply,
ebcf1f97
LP
209 void *userdata,
210 sd_bus_error *error) {
718db961
LP
211
212 ExecContext *c = userdata;
82c121a4
LP
213 int32_t n;
214
718db961
LP
215 assert(bus);
216 assert(reply);
82c121a4
LP
217 assert(c);
218
219 if (c->cpu_sched_set)
220 n = c->cpu_sched_priority;
221 else {
b92bea5d 222 struct sched_param p = {};
82c121a4 223
82c121a4
LP
224 if (sched_getparam(0, &p) >= 0)
225 n = p.sched_priority;
e62d8c39
ZJS
226 else
227 n = 0;
82c121a4
LP
228 }
229
718db961 230 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
231}
232
718db961
LP
233static int property_get_cpu_affinity(
234 sd_bus *bus,
235 const char *path,
236 const char *interface,
237 const char *property,
238 sd_bus_message *reply,
ebcf1f97
LP
239 void *userdata,
240 sd_bus_error *error) {
82c121a4 241
718db961 242 ExecContext *c = userdata;
82c121a4 243
718db961
LP
244 assert(bus);
245 assert(reply);
246 assert(c);
82c121a4
LP
247
248 if (c->cpuset)
718db961 249 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
82c121a4 250 else
718db961 251 return sd_bus_message_append_array(reply, 'y', NULL, 0);
82c121a4
LP
252}
253
718db961
LP
254static int property_get_timer_slack_nsec(
255 sd_bus *bus,
256 const char *path,
257 const char *interface,
258 const char *property,
259 sd_bus_message *reply,
ebcf1f97
LP
260 void *userdata,
261 sd_bus_error *error) {
718db961
LP
262
263 ExecContext *c = userdata;
82c121a4
LP
264 uint64_t u;
265
718db961
LP
266 assert(bus);
267 assert(reply);
82c121a4
LP
268 assert(c);
269
3a43da28 270 if (c->timer_slack_nsec != NSEC_INFINITY)
03fae018 271 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
272 else
273 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
274
718db961 275 return sd_bus_message_append(reply, "t", u);
82c121a4
LP
276}
277
718db961
LP
278static int property_get_capability_bounding_set(
279 sd_bus *bus,
280 const char *path,
281 const char *interface,
282 const char *property,
283 sd_bus_message *reply,
ebcf1f97
LP
284 void *userdata,
285 sd_bus_error *error) {
260abb78 286
718db961
LP
287 ExecContext *c = userdata;
288
289 assert(bus);
290 assert(reply);
260abb78
LP
291 assert(c);
292
7c3d67ef 293 /* We store this negated internally, to match the kernel, but
260abb78 294 * we expose it normalized. */
718db961 295 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
260abb78
LP
296}
297
718db961
LP
298static int property_get_capabilities(
299 sd_bus *bus,
300 const char *path,
301 const char *interface,
302 const char *property,
303 sd_bus_message *reply,
ebcf1f97
LP
304 void *userdata,
305 sd_bus_error *error) {
718db961
LP
306
307 ExecContext *c = userdata;
5ce70e5b 308 _cleanup_cap_free_charp_ char *t = NULL;
82c121a4 309 const char *s;
82c121a4 310
718db961
LP
311 assert(bus);
312 assert(reply);
82c121a4
LP
313 assert(c);
314
315 if (c->capabilities)
316 s = t = cap_to_text(c->capabilities, NULL);
317 else
318 s = "";
319
674cdd19 320 if (!s)
82c121a4
LP
321 return -ENOMEM;
322
5ce70e5b 323 return sd_bus_message_append(reply, "s", s);
82c121a4
LP
324}
325
718db961
LP
326static int property_get_syscall_filter(
327 sd_bus *bus,
328 const char *path,
329 const char *interface,
330 const char *property,
331 sd_bus_message *reply,
ebcf1f97
LP
332 void *userdata,
333 sd_bus_error *error) {
82c121a4 334
17df7223
LP
335 ExecContext *c = userdata;
336 _cleanup_strv_free_ char **l = NULL;
57183d11
LP
337 int r;
338
351a19b1 339#ifdef HAVE_SECCOMP
17df7223
LP
340 Iterator i;
341 void *id;
351a19b1 342#endif
17df7223
LP
343
344 assert(bus);
345 assert(reply);
346 assert(c);
347
57183d11
LP
348 r = sd_bus_message_open_container(reply, 'r', "bas");
349 if (r < 0)
350 return r;
351
352 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
353 if (r < 0)
354 return r;
355
351a19b1 356#ifdef HAVE_SECCOMP
17df7223
LP
357 SET_FOREACH(id, c->syscall_filter, i) {
358 char *name;
359
360 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
361 if (!name)
362 continue;
363
6e18964d
ZJS
364 r = strv_consume(&l, name);
365 if (r < 0)
366 return r;
17df7223 367 }
351a19b1 368#endif
17df7223
LP
369
370 strv_sort(l);
371
57183d11
LP
372 r = sd_bus_message_append_strv(reply, l);
373 if (r < 0)
374 return r;
17df7223 375
57183d11
LP
376 return sd_bus_message_close_container(reply);
377}
17df7223 378
57183d11
LP
379static int property_get_syscall_archs(
380 sd_bus *bus,
381 const char *path,
382 const char *interface,
383 const char *property,
384 sd_bus_message *reply,
385 void *userdata,
386 sd_bus_error *error) {
387
388 ExecContext *c = userdata;
389 _cleanup_strv_free_ char **l = NULL;
390 int r;
391
392#ifdef HAVE_SECCOMP
393 Iterator i;
394 void *id;
395#endif
396
397 assert(bus);
398 assert(reply);
399 assert(c);
17df7223 400
57183d11
LP
401#ifdef HAVE_SECCOMP
402 SET_FOREACH(id, c->syscall_archs, i) {
403 const char *name;
404
405 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
406 if (!name)
407 continue;
408
409 r = strv_extend(&l, name);
410 if (r < 0)
411 return -ENOMEM;
17df7223 412 }
57183d11
LP
413#endif
414
415 strv_sort(l);
416
417 r = sd_bus_message_append_strv(reply, l);
418 if (r < 0)
419 return r;
17df7223 420
57183d11 421 return 0;
17df7223
LP
422}
423
424static int property_get_syscall_errno(
425 sd_bus *bus,
426 const char *path,
427 const char *interface,
428 const char *property,
429 sd_bus_message *reply,
430 void *userdata,
431 sd_bus_error *error) {
432
718db961 433 ExecContext *c = userdata;
82c121a4 434
718db961
LP
435 assert(bus);
436 assert(reply);
437 assert(c);
82c121a4 438
17df7223 439 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
718db961 440}
82c121a4 441
5f8640fb
LP
442static int property_get_selinux_context(
443 sd_bus *bus,
444 const char *path,
445 const char *interface,
446 const char *property,
447 sd_bus_message *reply,
448 void *userdata,
449 sd_bus_error *error) {
450
451 ExecContext *c = userdata;
452
453 assert(bus);
454 assert(reply);
455 assert(c);
456
457 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
458}
459
eef65bf3
MS
460static int property_get_apparmor_profile(
461 sd_bus *bus,
462 const char *path,
463 const char *interface,
464 const char *property,
465 sd_bus_message *reply,
466 void *userdata,
467 sd_bus_error *error) {
468
469 ExecContext *c = userdata;
470
471 assert(bus);
472 assert(reply);
473 assert(c);
474
475 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
476}
477
2ca620c4
WC
478static int property_get_smack_process_label(
479 sd_bus *bus,
480 const char *path,
481 const char *interface,
482 const char *property,
483 sd_bus_message *reply,
484 void *userdata,
485 sd_bus_error *error) {
486
487 ExecContext *c = userdata;
488
489 assert(bus);
490 assert(reply);
491 assert(c);
492
493 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
494}
495
ac45f971
LP
496static int property_get_personality(
497 sd_bus *bus,
498 const char *path,
499 const char *interface,
500 const char *property,
501 sd_bus_message *reply,
502 void *userdata,
503 sd_bus_error *error) {
504
505 ExecContext *c = userdata;
506
507 assert(bus);
508 assert(reply);
509 assert(c);
510
511 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
512}
513
4298d0b5
LP
514static int property_get_address_families(
515 sd_bus *bus,
516 const char *path,
517 const char *interface,
518 const char *property,
519 sd_bus_message *reply,
520 void *userdata,
521 sd_bus_error *error) {
522
523 ExecContext *c = userdata;
524 _cleanup_strv_free_ char **l = NULL;
525 Iterator i;
526 void *af;
527 int r;
528
529 assert(bus);
530 assert(reply);
531 assert(c);
532
533 r = sd_bus_message_open_container(reply, 'r', "bas");
534 if (r < 0)
535 return r;
536
537 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
538 if (r < 0)
539 return r;
540
541 SET_FOREACH(af, c->address_families, i) {
542 const char *name;
543
544 name = af_to_name(PTR_TO_INT(af));
545 if (!name)
546 continue;
547
548 r = strv_extend(&l, name);
549 if (r < 0)
550 return -ENOMEM;
551 }
552
553 strv_sort(l);
554
555 r = sd_bus_message_append_strv(reply, l);
556 if (r < 0)
557 return r;
558
559 return sd_bus_message_close_container(reply);
560}
561
5f5d8eab
LP
562static int property_get_working_directory(
563 sd_bus *bus,
564 const char *path,
565 const char *interface,
566 const char *property,
567 sd_bus_message *reply,
568 void *userdata,
569 sd_bus_error *error) {
570
571 ExecContext *c = userdata;
572 const char *wd;
573
574 assert(bus);
575 assert(reply);
576 assert(c);
577
578 if (c->working_directory_home)
579 wd = "~";
580 else
581 wd = c->working_directory;
582
583 if (c->working_directory_missing_ok)
584 wd = strjoina("!", wd);
585
586 return sd_bus_message_append(reply, "s", wd);
587}
588
06f2ccf9
EV
589static int property_get_syslog_level(
590 sd_bus *bus,
591 const char *path,
592 const char *interface,
593 const char *property,
594 sd_bus_message *reply,
595 void *userdata,
596 sd_bus_error *error) {
597
598 ExecContext *c = userdata;
599
600 assert(bus);
601 assert(reply);
602 assert(c);
603
604 return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
605}
606
607static int property_get_syslog_facility(
608 sd_bus *bus,
609 const char *path,
610 const char *interface,
611 const char *property,
612 sd_bus_message *reply,
613 void *userdata,
614 sd_bus_error *error) {
615
616 ExecContext *c = userdata;
617
618 assert(bus);
619 assert(reply);
620 assert(c);
621
622 return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
623}
624
718db961
LP
625const sd_bus_vtable bus_exec_vtable[] = {
626 SD_BUS_VTABLE_START(0),
556089dc
LP
627 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
628 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
629 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3
EV
630 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
631 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
632 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
633 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
634 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
635 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
636 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
637 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
638 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
639 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
640 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
641 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
642 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
643 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
644 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
645 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
5f5d8eab 646 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
647 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
648 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
649 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
650 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
651 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
652 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
653 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
654 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
655 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
656 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
657 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
658 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
659 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
660 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
661 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
662 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
663 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
664 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
665 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
666 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
06f2ccf9
EV
667 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
668 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
669 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
670 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
671 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
672 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
673 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
674 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
675 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
676 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
677 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
678 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
679 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
680 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
681 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
7f112f50 682 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
1b8689f9
LP
683 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
684 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
685 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
686 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
023a4f67 687 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
5f8640fb 688 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
eef65bf3 689 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2ca620c4 690 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
691 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
692 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
57183d11
LP
693 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
694 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
17df7223 695 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
ac45f971 696 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
4298d0b5 697 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
e66cf1a3
LP
698 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
699 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
700 SD_BUS_VTABLE_END
701};
82c121a4 702
4d4c80d0
LP
703static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
704 int r;
705
706 assert(reply);
707 assert(c);
708
709 if (!c->path)
710 return 0;
711
712 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
713 if (r < 0)
714 return r;
715
716 r = sd_bus_message_append(reply, "s", c->path);
717 if (r < 0)
718 return r;
719
720 r = sd_bus_message_append_strv(reply, c->argv);
721 if (r < 0)
722 return r;
723
724 r = sd_bus_message_append(reply, "bttttuii",
725 c->ignore,
726 c->exec_status.start_timestamp.realtime,
727 c->exec_status.start_timestamp.monotonic,
728 c->exec_status.exit_timestamp.realtime,
729 c->exec_status.exit_timestamp.monotonic,
730 (uint32_t) c->exec_status.pid,
731 (int32_t) c->exec_status.code,
732 (int32_t) c->exec_status.status);
733 if (r < 0)
734 return r;
735
736 return sd_bus_message_close_container(reply);
737}
738
718db961
LP
739int bus_property_get_exec_command(
740 sd_bus *bus,
741 const char *path,
742 const char *interface,
743 const char *property,
744 sd_bus_message *reply,
ebcf1f97
LP
745 void *userdata,
746 sd_bus_error *ret_error) {
fe68089d 747
4d4c80d0 748 ExecCommand *c = (ExecCommand*) userdata;
718db961 749 int r;
fe68089d 750
718db961
LP
751 assert(bus);
752 assert(reply);
fe68089d 753
718db961
LP
754 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
755 if (r < 0)
756 return r;
fe68089d 757
4d4c80d0
LP
758 r = append_exec_command(reply, c);
759 if (r < 0)
760 return r;
fe68089d 761
4d4c80d0
LP
762 return sd_bus_message_close_container(reply);
763}
718db961 764
4d4c80d0
LP
765int bus_property_get_exec_command_list(
766 sd_bus *bus,
767 const char *path,
768 const char *interface,
769 const char *property,
770 sd_bus_message *reply,
771 void *userdata,
772 sd_bus_error *ret_error) {
718db961 773
4d4c80d0
LP
774 ExecCommand *c = *(ExecCommand**) userdata;
775 int r;
718db961 776
4d4c80d0
LP
777 assert(bus);
778 assert(reply);
779
780 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
781 if (r < 0)
782 return r;
718db961 783
4d4c80d0
LP
784 LIST_FOREACH(command, c, c) {
785 r = append_exec_command(reply, c);
718db961
LP
786 if (r < 0)
787 return r;
fe68089d
LP
788 }
789
718db961 790 return sd_bus_message_close_container(reply);
8351ceae 791}
c7040b5d
LP
792
793int bus_exec_context_set_transient_property(
794 Unit *u,
795 ExecContext *c,
796 const char *name,
797 sd_bus_message *message,
798 UnitSetPropertiesMode mode,
799 sd_bus_error *error) {
800
801 int r;
802
803 assert(u);
804 assert(c);
805 assert(name);
806 assert(message);
807
808 if (streq(name, "User")) {
809 const char *uu;
810
811 r = sd_bus_message_read(message, "s", &uu);
812 if (r < 0)
813 return r;
814
815 if (mode != UNIT_CHECK) {
816
817 if (isempty(uu)) {
a1e58e8e 818 c->user = mfree(c->user);
c7040b5d
LP
819 } else {
820 char *t;
821
822 t = strdup(uu);
823 if (!t)
824 return -ENOMEM;
825
826 free(c->user);
827 c->user = t;
828 }
829
830 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
831 }
832
833 return 1;
834
835 } else if (streq(name, "Group")) {
836 const char *gg;
837
838 r = sd_bus_message_read(message, "s", &gg);
839 if (r < 0)
840 return r;
841
842 if (mode != UNIT_CHECK) {
843
844 if (isempty(gg)) {
a1e58e8e 845 c->group = mfree(c->group);
c7040b5d
LP
846 } else {
847 char *t;
848
849 t = strdup(gg);
850 if (!t)
851 return -ENOMEM;
852
853 free(c->group);
854 c->group = t;
855 }
856
857 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
858 }
859
860 return 1;
de53c417
EV
861 } else if (streq(name, "SyslogIdentifier")) {
862 const char *id;
c7040b5d 863
de53c417
EV
864 r = sd_bus_message_read(message, "s", &id);
865 if (r < 0)
866 return r;
867
868 if (mode != UNIT_CHECK) {
869
870 if (isempty(id)) {
871 c->syslog_identifier = mfree(c->syslog_identifier);
872 } else {
873 char *t;
874
875 t = strdup(id);
876 if (!t)
877 return -ENOMEM;
878
879 free(c->syslog_identifier);
880 c->syslog_identifier = t;
881 }
882
883 unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s\n", id);
884 }
885
a8a13575
EV
886 return 1;
887 } else if (streq(name, "SyslogLevel")) {
888 int level;
889
890 r = sd_bus_message_read(message, "i", &level);
891 if (r < 0)
892 return r;
893
e0d6e0fa
EV
894 if (!log_level_is_valid(level))
895 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
896
a8a13575
EV
897 if (mode != UNIT_CHECK) {
898 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
899 unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i\n", level);
900 }
901
460ed929
EV
902 return 1;
903 } else if (streq(name, "SyslogFacility")) {
904 int facility;
905
906 r = sd_bus_message_read(message, "i", &facility);
907 if (r < 0)
908 return r;
909
e0d6e0fa
EV
910 if (!log_facility_unshifted_is_valid(facility))
911 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
912
460ed929
EV
913 if (mode != UNIT_CHECK) {
914 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
915 unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i\n", facility);
916 }
917
de53c417 918 return 1;
c7040b5d
LP
919 } else if (streq(name, "Nice")) {
920 int n;
921
922 r = sd_bus_message_read(message, "i", &n);
923 if (r < 0)
924 return r;
925
926 if (n < PRIO_MIN || n >= PRIO_MAX)
927 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
928
929 if (mode != UNIT_CHECK) {
930 c->nice = n;
931 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
932 }
933
934 return 1;
935
5f5d8eab 936 } else if (STR_IN_SET(name, "TTYPath", "RootDirectory")) {
602b8355 937 const char *s;
9b15b784 938
602b8355 939 r = sd_bus_message_read(message, "s", &s);
9b15b784
LP
940 if (r < 0)
941 return r;
942
602b8355
NC
943 if (!path_is_absolute(s))
944 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
9b15b784
LP
945
946 if (mode != UNIT_CHECK) {
5f5d8eab
LP
947 if (streq(name, "TTYPath"))
948 r = free_and_strdup(&c->tty_path, s);
949 else {
950 assert(streq(name, "RootDirectory"));
951 r = free_and_strdup(&c->root_directory, s);
602b8355 952 }
5f5d8eab
LP
953 if (r < 0)
954 return r;
9b15b784 955
602b8355 956 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
9b15b784
LP
957 }
958
959 return 1;
960
5f5d8eab
LP
961 } else if (streq(name, "WorkingDirectory")) {
962 const char *s;
963 bool missing_ok;
964
965 r = sd_bus_message_read(message, "s", &s);
966 if (r < 0)
967 return r;
968
969 if (s[0] == '-') {
970 missing_ok = true;
971 s++;
972 } else
973 missing_ok = false;
974
975 if (!streq(s, "~") && !path_is_absolute(s))
976 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
977
978 if (mode != UNIT_CHECK) {
979 if (streq(s, "~")) {
980 c->working_directory = mfree(c->working_directory);
981 c->working_directory_home = true;
982 } else {
983 r = free_and_strdup(&c->working_directory, s);
984 if (r < 0)
985 return r;
986
987 c->working_directory_home = false;
988 }
989
990 c->working_directory_missing_ok = missing_ok;
991 unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
992 }
993
994 return 1;
995
9b15b784
LP
996 } else if (streq(name, "StandardInput")) {
997 const char *s;
998 ExecInput p;
999
1000 r = sd_bus_message_read(message, "s", &s);
1001 if (r < 0)
1002 return r;
1003
1004 p = exec_input_from_string(s);
1005 if (p < 0)
1006 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
1007
1008 if (mode != UNIT_CHECK) {
1009 c->std_input = p;
1010
1011 unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s\n", exec_input_to_string(p));
1012 }
1013
1014 return 1;
1015
1016
1017 } else if (streq(name, "StandardOutput")) {
1018 const char *s;
1019 ExecOutput p;
1020
1021 r = sd_bus_message_read(message, "s", &s);
1022 if (r < 0)
1023 return r;
1024
1025 p = exec_output_from_string(s);
1026 if (p < 0)
1027 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
1028
1029 if (mode != UNIT_CHECK) {
1030 c->std_output = p;
1031
1032 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s\n", exec_output_to_string(p));
1033 }
1034
1035 return 1;
1036
1037 } else if (streq(name, "StandardError")) {
1038 const char *s;
1039 ExecOutput p;
1040
1041 r = sd_bus_message_read(message, "s", &s);
1042 if (r < 0)
1043 return r;
1044
1045 p = exec_output_from_string(s);
1046 if (p < 0)
1047 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
1048
1049 if (mode != UNIT_CHECK) {
1050 c->std_error = p;
1051
1052 unit_write_drop_in_private_format(u, mode, name, "StandardError=%s\n", exec_output_to_string(p));
1053 }
1054
1055 return 1;
1056
b9c50073
GP
1057 } else if (STR_IN_SET(name,
1058 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1059 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
047d9933 1060 "NoNewPrivileges", "SyslogLevelPrefix")) {
506711fd
LP
1061 int b;
1062
1063 r = sd_bus_message_read(message, "b", &b);
1064 if (r < 0)
1065 return r;
1066
1067 if (mode != UNIT_CHECK) {
b9c50073
GP
1068 if (streq(name, "IgnoreSIGPIPE"))
1069 c->ignore_sigpipe = b;
1070 else if (streq(name, "TTYVHangup"))
1071 c->tty_vhangup = b;
1072 else if (streq(name, "TTYReset"))
1073 c->tty_reset = b;
1074 else if (streq(name, "PrivateTmp"))
1075 c->private_tmp = b;
1076 else if (streq(name, "PrivateDevices"))
1077 c->private_devices = b;
1078 else if (streq(name, "PrivateNetwork"))
1079 c->private_network = b;
1080 else if (streq(name, "NoNewPrivileges"))
1081 c->no_new_privileges = b;
047d9933
EV
1082 else if (streq(name, "SyslogLevelPrefix"))
1083 c->syslog_level_prefix = b;
b9c50073
GP
1084
1085 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, yes_no(b));
506711fd
LP
1086 }
1087
1088 return 1;
1089
1090 } else if (streq(name, "UtmpIdentifier")) {
1091 const char *id;
1092
1093 r = sd_bus_message_read(message, "s", &id);
1094 if (r < 0)
1095 return r;
1096
1097 if (mode != UNIT_CHECK) {
1098 if (isempty(id))
1099 c->utmp_id = mfree(c->utmp_id);
1100 else if (free_and_strdup(&c->utmp_id, id) < 0)
1101 return -ENOMEM;
1102
1103 unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s\n", strempty(id));
1104 }
1105
1106 return 1;
1107
1108 } else if (streq(name, "UtmpMode")) {
1109 const char *s;
1110 ExecUtmpMode m;
1111
1112 r = sd_bus_message_read(message, "s", &s);
1113 if (r < 0)
1114 return r;
1115
1116 m = exec_utmp_mode_from_string(s);
1117 if (m < 0)
1118 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
1119
1120 if (mode != UNIT_CHECK) {
1121 c->utmp_mode = m;
1122
1123 unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s\n", exec_utmp_mode_to_string(m));
1124 }
1125
1126 return 1;
1127
1128 } else if (streq(name, "PAMName")) {
1129 const char *n;
1130
1131 r = sd_bus_message_read(message, "s", &n);
1132 if (r < 0)
1133 return r;
1134
1135 if (mode != UNIT_CHECK) {
1136 if (isempty(n))
1137 c->pam_name = mfree(c->pam_name);
1138 else if (free_and_strdup(&c->pam_name, n) < 0)
1139 return -ENOMEM;
1140
1141 unit_write_drop_in_private_format(u, mode, name, "PAMName=%s\n", strempty(n));
1142 }
1143
1144 return 1;
1145
c7040b5d
LP
1146 } else if (streq(name, "Environment")) {
1147
1148 _cleanup_strv_free_ char **l = NULL;
1149
1150 r = sd_bus_message_read_strv(message, &l);
1151 if (r < 0)
1152 return r;
1153
1154 if (!strv_env_is_valid(l))
1155 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1156
1157 if (mode != UNIT_CHECK) {
1006a62d 1158 _cleanup_free_ char *joined = NULL;
c7040b5d
LP
1159 char **e;
1160
e9876fc9
EV
1161 if (strv_length(l) == 0) {
1162 c->environment = strv_free(c->environment);
1163 unit_write_drop_in_private_format(u, mode, name, "Environment=\n");
1164 } else {
1165 e = strv_env_merge(2, c->environment, l);
1166 if (!e)
1167 return -ENOMEM;
c7040b5d 1168
e9876fc9
EV
1169 strv_free(c->environment);
1170 c->environment = e;
c7040b5d 1171
e9876fc9
EV
1172 joined = strv_join_quoted(c->environment);
1173 if (!joined)
1174 return -ENOMEM;
1175
1176 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
1177 }
c7040b5d
LP
1178 }
1179
d584f638
LP
1180 return 1;
1181
f1db3327
EV
1182 } else if (streq(name, "TimerSlackNSec")) {
1183
1184 nsec_t n;
1185
1186 r = sd_bus_message_read(message, "t", &n);
1187 if (r < 0)
1188 return r;
1189
1190 if (mode != UNIT_CHECK) {
1191 c->timer_slack_nsec = n;
1192 unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT "\n", n);
1193 }
1194
1195 return 1;
1196
6b862936
EV
1197 } else if (streq(name, "OOMScoreAdjust")) {
1198 int oa;
1199
1200 r = sd_bus_message_read(message, "i", &oa);
1201 if (r < 0)
1202 return r;
1203
1204 if (!oom_score_adjust_is_valid(oa))
1205 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
1206
1207 if (mode != UNIT_CHECK) {
1208 c->oom_score_adjust = oa;
1209 c->oom_score_adjust_set = true;
1210 unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i\n", oa);
1211 }
1212
1213 return 1;
1214
ceb728cf
NC
1215 } else if (streq(name, "EnvironmentFiles")) {
1216
1217 _cleanup_free_ char *joined = NULL;
1218 _cleanup_fclose_ FILE *f = NULL;
2229f656 1219 _cleanup_free_ char **l = NULL;
ceb728cf 1220 size_t size = 0;
2229f656 1221 char **i;
ceb728cf
NC
1222
1223 r = sd_bus_message_enter_container(message, 'a', "(sb)");
1224 if (r < 0)
1225 return r;
1226
1227 f = open_memstream(&joined, &size);
1228 if (!f)
1229 return -ENOMEM;
1230
2229f656
LP
1231 STRV_FOREACH(i, c->environment_files)
1232 fprintf(f, "EnvironmentFile=%s\n", *i);
ceb728cf
NC
1233
1234 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
1235 const char *path;
1236 int b;
1237
ceb728cf
NC
1238 r = sd_bus_message_read(message, "sb", &path, &b);
1239 if (r < 0)
1240 return r;
1241
1242 r = sd_bus_message_exit_container(message);
1243 if (r < 0)
1244 return r;
1245
1246 if (!isempty(path) && !path_is_absolute(path))
1247 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
1248
1249 if (mode != UNIT_CHECK) {
ceb728cf
NC
1250 char *buf = NULL;
1251
1252 buf = strjoin(b ? "-" : "", path, NULL);
2229f656 1253 if (!buf)
ceb728cf
NC
1254 return -ENOMEM;
1255
1256 fprintf(f, "EnvironmentFile=%s\n", buf);
1257
2229f656 1258 r = strv_consume(&l, buf);
ceb728cf
NC
1259 if (r < 0)
1260 return r;
1261 }
1262 }
1263 if (r < 0)
1264 return r;
1265
b0830e21
LP
1266 r = sd_bus_message_exit_container(message);
1267 if (r < 0)
1268 return r;
1269
2229f656
LP
1270 r = fflush_and_check(f);
1271 if (r < 0)
1272 return r;
ceb728cf 1273
2229f656
LP
1274 if (mode != UNIT_CHECK) {
1275 if (strv_isempty(l)) {
1276 c->environment_files = strv_free(c->environment_files);
ceb728cf 1277 unit_write_drop_in_private(u, mode, name, "EnvironmentFile=\n");
2229f656
LP
1278 } else {
1279 r = strv_extend_strv(&c->environment_files, l, true);
1280 if (r < 0)
1281 return r;
1282
ceb728cf 1283 unit_write_drop_in_private(u, mode, name, joined);
2229f656
LP
1284 }
1285 }
ceb728cf 1286
ceb728cf
NC
1287 return 1;
1288
08596068
EV
1289 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1290
1291 _cleanup_strv_free_ char **l = NULL;
1292 char ***dirs;
1293 char **p;
1294
1295 r = sd_bus_message_read_strv(message, &l);
1296 if (r < 0)
1297 return r;
1298
1299 STRV_FOREACH(p, l) {
1300 int offset;
1301 if (!utf8_is_valid(*p))
1302 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1303
1304 offset = **p == '-';
1305 if (!path_is_absolute(*p + offset))
1306 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1307 }
1308
1309 if (mode != UNIT_CHECK) {
1310 _cleanup_free_ char *joined = NULL;
1311
1312 if (streq(name, "ReadWriteDirectories"))
1313 dirs = &c->read_write_dirs;
1314 else if (streq(name, "ReadOnlyDirectories"))
1315 dirs = &c->read_only_dirs;
1316 else if (streq(name, "InaccessibleDirectories"))
1317 dirs = &c->inaccessible_dirs;
1318
1319 if (strv_length(l) == 0) {
1320 *dirs = strv_free(*dirs);
1321 unit_write_drop_in_private_format(u, mode, name, "%s=\n", name);
1322 } else {
1323 r = strv_extend_strv(dirs, l, true);
1324
1325 if (r < 0)
1326 return -ENOMEM;
1327
1328 joined = strv_join_quoted(*dirs);
1329 if (!joined)
1330 return -ENOMEM;
1331
1332 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, joined);
1333 }
1334
1335 }
1336
1337 return 1;
1338
5664e6cf
EV
1339 } else if (streq(name, "ProtectSystem")) {
1340 const char *s;
1341 ProtectSystem ps;
1342
1343 r = sd_bus_message_read(message, "s", &s);
1344 if (r < 0)
1345 return r;
1346
1347 r = parse_boolean(s);
1348 if (r > 0)
1349 ps = PROTECT_SYSTEM_YES;
1350 else if (r == 0)
1351 ps = PROTECT_SYSTEM_NO;
1352 else {
1353 ps = protect_system_from_string(s);
1354 if (ps < 0)
1355 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value");
1356 }
1357
1358 if (mode != UNIT_CHECK) {
1359 c->protect_system = ps;
1360 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
1361 }
1362
1363 return 1;
1364
eff58074
EV
1365 } else if (streq(name, "ProtectHome")) {
1366 const char *s;
1367 ProtectHome ph;
1368
1369 r = sd_bus_message_read(message, "s", &s);
1370 if (r < 0)
1371 return r;
1372
1373 r = parse_boolean(s);
1374 if (r > 0)
1375 ph = PROTECT_HOME_YES;
1376 else if (r == 0)
1377 ph = PROTECT_HOME_NO;
1378 else {
1379 ph = protect_home_from_string(s);
1380 if (ph < 0)
1381 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value");
1382 }
1383
1384 if (mode != UNIT_CHECK) {
1385 c->protect_home = ph;
1386 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
1387 }
1388
1389 return 1;
1390
d584f638
LP
1391 } else if (rlimit_from_string(name) >= 0) {
1392 uint64_t rl;
1393 rlim_t x;
1394
1395 r = sd_bus_message_read(message, "t", &rl);
1396 if (r < 0)
1397 return r;
1398
1399 if (rl == (uint64_t) -1)
1400 x = RLIM_INFINITY;
1401 else {
1402 x = (rlim_t) rl;
1403
1404 if ((uint64_t) x != rl)
1405 return -ERANGE;
1406 }
1407
1408 if (mode != UNIT_CHECK) {
1409 int z;
1410
1411 z = rlimit_from_string(name);
1412
1413 if (!c->rlimit[z]) {
1414 c->rlimit[z] = new(struct rlimit, 1);
1415 if (!c->rlimit[z])
1416 return -ENOMEM;
1417 }
1418
1419 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
1420
1421 if (x == RLIM_INFINITY)
1422 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
1423 else
1424 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
1425 }
1426
c7040b5d
LP
1427 return 1;
1428 }
1429
1430 return 0;
1431}