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