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