]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
tree-wide: drop 'This file is part of systemd' blurb
[thirdparty/systemd.git] / src / core / dbus-execute.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 Copyright 2010 Lennart Poettering
4 ***/
5
6 #include <sys/mount.h>
7 #include <sys/prctl.h>
8 #include <stdio_ext.h>
9
10 #if HAVE_SECCOMP
11 #include <seccomp.h>
12 #endif
13
14 #include "af-list.h"
15 #include "alloc-util.h"
16 #include "bus-util.h"
17 #include "cap-list.h"
18 #include "capability-util.h"
19 #include "cpu-set-util.h"
20 #include "dbus-execute.h"
21 #include "dbus-util.h"
22 #include "env-util.h"
23 #include "errno-list.h"
24 #include "escape.h"
25 #include "execute.h"
26 #include "fd-util.h"
27 #include "fileio.h"
28 #include "hexdecoct.h"
29 #include "io-util.h"
30 #include "ioprio.h"
31 #include "journal-util.h"
32 #include "missing.h"
33 #include "mount-util.h"
34 #include "namespace.h"
35 #include "parse-util.h"
36 #include "path-util.h"
37 #include "process-util.h"
38 #include "rlimit-util.h"
39 #if HAVE_SECCOMP
40 #include "seccomp-util.h"
41 #endif
42 #include "securebits-util.h"
43 #include "specifier.h"
44 #include "strv.h"
45 #include "syslog-util.h"
46 #include "unit-printf.h"
47 #include "user-util.h"
48 #include "utf8.h"
49
50 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
51 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
52 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
53 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
54 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode);
55 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_home, protect_home, ProtectHome);
56 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system, protect_system, ProtectSystem);
57 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality, personality, unsigned long);
58 static BUS_DEFINE_PROPERTY_GET(property_get_ioprio, "i", ExecContext, exec_context_get_effective_ioprio);
59 static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_class, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_CLASS);
60 static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_DATA);
61 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL);
62 static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI);
63 static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC);
64
65 static int property_get_environment_files(
66 sd_bus *bus,
67 const char *path,
68 const char *interface,
69 const char *property,
70 sd_bus_message *reply,
71 void *userdata,
72 sd_bus_error *error) {
73
74 ExecContext *c = userdata;
75 char **j;
76 int r;
77
78 assert(bus);
79 assert(reply);
80 assert(c);
81
82 r = sd_bus_message_open_container(reply, 'a', "(sb)");
83 if (r < 0)
84 return r;
85
86 STRV_FOREACH(j, c->environment_files) {
87 const char *fn = *j;
88
89 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
90 if (r < 0)
91 return r;
92 }
93
94 return sd_bus_message_close_container(reply);
95 }
96
97 static int property_get_oom_score_adjust(
98 sd_bus *bus,
99 const char *path,
100 const char *interface,
101 const char *property,
102 sd_bus_message *reply,
103 void *userdata,
104 sd_bus_error *error) {
105
106 ExecContext *c = userdata;
107 int32_t n;
108
109 assert(bus);
110 assert(reply);
111 assert(c);
112
113 if (c->oom_score_adjust_set)
114 n = c->oom_score_adjust;
115 else {
116 _cleanup_free_ char *t = NULL;
117
118 n = 0;
119 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
120 safe_atoi32(t, &n);
121 }
122
123 return sd_bus_message_append(reply, "i", n);
124 }
125
126 static int property_get_nice(
127 sd_bus *bus,
128 const char *path,
129 const char *interface,
130 const char *property,
131 sd_bus_message *reply,
132 void *userdata,
133 sd_bus_error *error) {
134
135 ExecContext *c = userdata;
136 int32_t n;
137
138 assert(bus);
139 assert(reply);
140 assert(c);
141
142 if (c->nice_set)
143 n = c->nice;
144 else {
145 errno = 0;
146 n = getpriority(PRIO_PROCESS, 0);
147 if (errno > 0)
148 n = 0;
149 }
150
151 return sd_bus_message_append(reply, "i", n);
152 }
153
154 static int property_get_cpu_sched_policy(
155 sd_bus *bus,
156 const char *path,
157 const char *interface,
158 const char *property,
159 sd_bus_message *reply,
160 void *userdata,
161 sd_bus_error *error) {
162
163 ExecContext *c = userdata;
164 int32_t n;
165
166 assert(bus);
167 assert(reply);
168 assert(c);
169
170 if (c->cpu_sched_set)
171 n = c->cpu_sched_policy;
172 else {
173 n = sched_getscheduler(0);
174 if (n < 0)
175 n = SCHED_OTHER;
176 }
177
178 return sd_bus_message_append(reply, "i", n);
179 }
180
181 static int property_get_cpu_sched_priority(
182 sd_bus *bus,
183 const char *path,
184 const char *interface,
185 const char *property,
186 sd_bus_message *reply,
187 void *userdata,
188 sd_bus_error *error) {
189
190 ExecContext *c = userdata;
191 int32_t n;
192
193 assert(bus);
194 assert(reply);
195 assert(c);
196
197 if (c->cpu_sched_set)
198 n = c->cpu_sched_priority;
199 else {
200 struct sched_param p = {};
201
202 if (sched_getparam(0, &p) >= 0)
203 n = p.sched_priority;
204 else
205 n = 0;
206 }
207
208 return sd_bus_message_append(reply, "i", n);
209 }
210
211 static int property_get_cpu_affinity(
212 sd_bus *bus,
213 const char *path,
214 const char *interface,
215 const char *property,
216 sd_bus_message *reply,
217 void *userdata,
218 sd_bus_error *error) {
219
220 ExecContext *c = userdata;
221
222 assert(bus);
223 assert(reply);
224 assert(c);
225
226 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
227 }
228
229 static int property_get_timer_slack_nsec(
230 sd_bus *bus,
231 const char *path,
232 const char *interface,
233 const char *property,
234 sd_bus_message *reply,
235 void *userdata,
236 sd_bus_error *error) {
237
238 ExecContext *c = userdata;
239 uint64_t u;
240
241 assert(bus);
242 assert(reply);
243 assert(c);
244
245 if (c->timer_slack_nsec != NSEC_INFINITY)
246 u = (uint64_t) c->timer_slack_nsec;
247 else
248 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
249
250 return sd_bus_message_append(reply, "t", u);
251 }
252
253 static int property_get_syscall_filter(
254 sd_bus *bus,
255 const char *path,
256 const char *interface,
257 const char *property,
258 sd_bus_message *reply,
259 void *userdata,
260 sd_bus_error *error) {
261
262 ExecContext *c = userdata;
263 _cleanup_strv_free_ char **l = NULL;
264 int r;
265
266 #if HAVE_SECCOMP
267 Iterator i;
268 void *id, *val;
269 #endif
270
271 assert(bus);
272 assert(reply);
273 assert(c);
274
275 r = sd_bus_message_open_container(reply, 'r', "bas");
276 if (r < 0)
277 return r;
278
279 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
280 if (r < 0)
281 return r;
282
283 #if HAVE_SECCOMP
284 HASHMAP_FOREACH_KEY(val, id, c->syscall_filter, i) {
285 _cleanup_free_ char *name = NULL;
286 const char *e = NULL;
287 char *s;
288 int num = PTR_TO_INT(val);
289
290 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
291 if (!name)
292 continue;
293
294 if (num >= 0) {
295 e = errno_to_name(num);
296 if (e) {
297 s = strjoin(name, ":", e);
298 if (!s)
299 return -ENOMEM;
300 } else {
301 r = asprintf(&s, "%s:%d", name, num);
302 if (r < 0)
303 return -ENOMEM;
304 }
305 } else
306 s = TAKE_PTR(name);
307
308 r = strv_consume(&l, s);
309 if (r < 0)
310 return r;
311 }
312 #endif
313
314 strv_sort(l);
315
316 r = sd_bus_message_append_strv(reply, l);
317 if (r < 0)
318 return r;
319
320 return sd_bus_message_close_container(reply);
321 }
322
323 static int property_get_syscall_archs(
324 sd_bus *bus,
325 const char *path,
326 const char *interface,
327 const char *property,
328 sd_bus_message *reply,
329 void *userdata,
330 sd_bus_error *error) {
331
332 ExecContext *c = userdata;
333 _cleanup_strv_free_ char **l = NULL;
334 int r;
335
336 #if HAVE_SECCOMP
337 Iterator i;
338 void *id;
339 #endif
340
341 assert(bus);
342 assert(reply);
343 assert(c);
344
345 #if HAVE_SECCOMP
346 SET_FOREACH(id, c->syscall_archs, i) {
347 const char *name;
348
349 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
350 if (!name)
351 continue;
352
353 r = strv_extend(&l, name);
354 if (r < 0)
355 return -ENOMEM;
356 }
357 #endif
358
359 strv_sort(l);
360
361 r = sd_bus_message_append_strv(reply, l);
362 if (r < 0)
363 return r;
364
365 return 0;
366 }
367
368 static int property_get_selinux_context(
369 sd_bus *bus,
370 const char *path,
371 const char *interface,
372 const char *property,
373 sd_bus_message *reply,
374 void *userdata,
375 sd_bus_error *error) {
376
377 ExecContext *c = userdata;
378
379 assert(bus);
380 assert(reply);
381 assert(c);
382
383 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
384 }
385
386 static int property_get_apparmor_profile(
387 sd_bus *bus,
388 const char *path,
389 const char *interface,
390 const char *property,
391 sd_bus_message *reply,
392 void *userdata,
393 sd_bus_error *error) {
394
395 ExecContext *c = userdata;
396
397 assert(bus);
398 assert(reply);
399 assert(c);
400
401 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
402 }
403
404 static int property_get_smack_process_label(
405 sd_bus *bus,
406 const char *path,
407 const char *interface,
408 const char *property,
409 sd_bus_message *reply,
410 void *userdata,
411 sd_bus_error *error) {
412
413 ExecContext *c = userdata;
414
415 assert(bus);
416 assert(reply);
417 assert(c);
418
419 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
420 }
421
422 static int property_get_address_families(
423 sd_bus *bus,
424 const char *path,
425 const char *interface,
426 const char *property,
427 sd_bus_message *reply,
428 void *userdata,
429 sd_bus_error *error) {
430
431 ExecContext *c = userdata;
432 _cleanup_strv_free_ char **l = NULL;
433 Iterator i;
434 void *af;
435 int r;
436
437 assert(bus);
438 assert(reply);
439 assert(c);
440
441 r = sd_bus_message_open_container(reply, 'r', "bas");
442 if (r < 0)
443 return r;
444
445 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
446 if (r < 0)
447 return r;
448
449 SET_FOREACH(af, c->address_families, i) {
450 const char *name;
451
452 name = af_to_name(PTR_TO_INT(af));
453 if (!name)
454 continue;
455
456 r = strv_extend(&l, name);
457 if (r < 0)
458 return -ENOMEM;
459 }
460
461 strv_sort(l);
462
463 r = sd_bus_message_append_strv(reply, l);
464 if (r < 0)
465 return r;
466
467 return sd_bus_message_close_container(reply);
468 }
469
470 static int property_get_working_directory(
471 sd_bus *bus,
472 const char *path,
473 const char *interface,
474 const char *property,
475 sd_bus_message *reply,
476 void *userdata,
477 sd_bus_error *error) {
478
479 ExecContext *c = userdata;
480 const char *wd;
481
482 assert(bus);
483 assert(reply);
484 assert(c);
485
486 if (c->working_directory_home)
487 wd = "~";
488 else
489 wd = c->working_directory;
490
491 if (c->working_directory_missing_ok)
492 wd = strjoina("!", wd);
493
494 return sd_bus_message_append(reply, "s", wd);
495 }
496
497 static int property_get_stdio_fdname(
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 int fileno;
508
509 assert(bus);
510 assert(c);
511 assert(property);
512 assert(reply);
513
514 if (streq(property, "StandardInputFileDescriptorName"))
515 fileno = STDIN_FILENO;
516 else if (streq(property, "StandardOutputFileDescriptorName"))
517 fileno = STDOUT_FILENO;
518 else {
519 assert(streq(property, "StandardErrorFileDescriptorName"));
520 fileno = STDERR_FILENO;
521 }
522
523 return sd_bus_message_append(reply, "s", exec_context_fdname(c, fileno));
524 }
525
526 static int property_get_input_data(
527 sd_bus *bus,
528 const char *path,
529 const char *interface,
530 const char *property,
531 sd_bus_message *reply,
532 void *userdata,
533 sd_bus_error *error) {
534
535 ExecContext *c = userdata;
536
537 assert(bus);
538 assert(c);
539 assert(property);
540 assert(reply);
541
542 return sd_bus_message_append_array(reply, 'y', c->stdin_data, c->stdin_data_size);
543 }
544
545 static int property_get_bind_paths(
546 sd_bus *bus,
547 const char *path,
548 const char *interface,
549 const char *property,
550 sd_bus_message *reply,
551 void *userdata,
552 sd_bus_error *error) {
553
554 ExecContext *c = userdata;
555 unsigned i;
556 bool ro;
557 int r;
558
559 assert(bus);
560 assert(c);
561 assert(property);
562 assert(reply);
563
564 ro = strstr(property, "ReadOnly");
565
566 r = sd_bus_message_open_container(reply, 'a', "(ssbt)");
567 if (r < 0)
568 return r;
569
570 for (i = 0; i < c->n_bind_mounts; i++) {
571
572 if (ro != c->bind_mounts[i].read_only)
573 continue;
574
575 r = sd_bus_message_append(
576 reply, "(ssbt)",
577 c->bind_mounts[i].source,
578 c->bind_mounts[i].destination,
579 c->bind_mounts[i].ignore_enoent,
580 c->bind_mounts[i].recursive ? (uint64_t) MS_REC : (uint64_t) 0);
581 if (r < 0)
582 return r;
583 }
584
585 return sd_bus_message_close_container(reply);
586 }
587
588 static int property_get_temporary_filesystems(
589 sd_bus *bus,
590 const char *path,
591 const char *interface,
592 const char *property,
593 sd_bus_message *reply,
594 void *userdata,
595 sd_bus_error *error) {
596
597 ExecContext *c = userdata;
598 unsigned i;
599 int r;
600
601 assert(bus);
602 assert(c);
603 assert(property);
604 assert(reply);
605
606 r = sd_bus_message_open_container(reply, 'a', "(ss)");
607 if (r < 0)
608 return r;
609
610 for (i = 0; i < c->n_temporary_filesystems; i++) {
611 TemporaryFileSystem *t = c->temporary_filesystems + i;
612
613 r = sd_bus_message_append(
614 reply, "(ss)",
615 t->path,
616 t->options);
617 if (r < 0)
618 return r;
619 }
620
621 return sd_bus_message_close_container(reply);
622 }
623
624 static int property_get_log_extra_fields(
625 sd_bus *bus,
626 const char *path,
627 const char *interface,
628 const char *property,
629 sd_bus_message *reply,
630 void *userdata,
631 sd_bus_error *error) {
632
633 ExecContext *c = userdata;
634 size_t i;
635 int r;
636
637 assert(bus);
638 assert(c);
639 assert(property);
640 assert(reply);
641
642 r = sd_bus_message_open_container(reply, 'a', "ay");
643 if (r < 0)
644 return r;
645
646 for (i = 0; i < c->n_log_extra_fields; i++) {
647 r = sd_bus_message_append_array(reply, 'y', c->log_extra_fields[i].iov_base, c->log_extra_fields[i].iov_len);
648 if (r < 0)
649 return r;
650 }
651
652 return sd_bus_message_close_container(reply);
653 }
654
655 const sd_bus_vtable bus_exec_vtable[] = {
656 SD_BUS_VTABLE_START(0),
657 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
658 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
659 SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
660 SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL, offsetof(ExecContext, unset_environment), SD_BUS_VTABLE_PROPERTY_CONST),
661 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
662 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
663 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
664 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
665 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
666 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
667 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
668 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
669 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
670 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
671 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
672 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
673 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
674 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
675 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
676 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
677 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
678 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
679 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
680 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
681 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
682 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
683 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
684 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
685 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
686 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
687 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
688 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
689 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
690 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
691 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
692 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
693 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
694 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
695 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
696 SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
697 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
698 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
699 SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST),
700 SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
701 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
702 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
703 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
704 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
705 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
706 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
707 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
708 SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
709 SD_BUS_PROPERTY("StandardInputData", "ay", property_get_input_data, 0, SD_BUS_VTABLE_PROPERTY_CONST),
710 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
711 SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
712 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
713 SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
714 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
715 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
716 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
717 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
718 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
719 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
720 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
721 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
722 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
723 SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int, offsetof(ExecContext, log_level_max), SD_BUS_VTABLE_PROPERTY_CONST),
724 SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields, 0, SD_BUS_VTABLE_PROPERTY_CONST),
725 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
726 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", NULL, offsetof(ExecContext, capability_bounding_set), SD_BUS_VTABLE_PROPERTY_CONST),
727 SD_BUS_PROPERTY("AmbientCapabilities", "t", NULL, offsetof(ExecContext, capability_ambient_set), SD_BUS_VTABLE_PROPERTY_CONST),
728 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
729 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
730 SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
731 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
732 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
733 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
734 SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST),
735 SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST),
736 SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
737 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
738 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
739 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
740 SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST),
741 SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_modules), SD_BUS_VTABLE_PROPERTY_CONST),
742 SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST),
743 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
744 SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
745 SD_BUS_PROPERTY("PrivateMounts", "b", bus_property_get_bool, offsetof(ExecContext, private_mounts), SD_BUS_VTABLE_PROPERTY_CONST),
746 SD_BUS_PROPERTY("ProtectHome", "s", property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
747 SD_BUS_PROPERTY("ProtectSystem", "s", property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
748 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
749 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
750 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
751 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
752 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
753 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
754 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
755 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
756 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
757 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
758 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST),
759 SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST),
760 SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
761 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
762 SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
763 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].mode), SD_BUS_VTABLE_PROPERTY_CONST),
764 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].paths), SD_BUS_VTABLE_PROPERTY_CONST),
765 SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
766 SD_BUS_PROPERTY("StateDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
767 SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
768 SD_BUS_PROPERTY("CacheDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
769 SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST),
770 SD_BUS_PROPERTY("LogsDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].paths), SD_BUS_VTABLE_PROPERTY_CONST),
771 SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST),
772 SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST),
773 SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
774 SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
775 SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
776 SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
777 SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
778 SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems, 0, SD_BUS_VTABLE_PROPERTY_CONST),
779 SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST),
780 SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST),
781
782 /* Obsolete/redundant properties: */
783 SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
784 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
785 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
786 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
787 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
788
789 SD_BUS_VTABLE_END
790 };
791
792 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
793 int r;
794
795 assert(reply);
796 assert(c);
797
798 if (!c->path)
799 return 0;
800
801 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
802 if (r < 0)
803 return r;
804
805 r = sd_bus_message_append(reply, "s", c->path);
806 if (r < 0)
807 return r;
808
809 r = sd_bus_message_append_strv(reply, c->argv);
810 if (r < 0)
811 return r;
812
813 r = sd_bus_message_append(reply, "bttttuii",
814 !!(c->flags & EXEC_COMMAND_IGNORE_FAILURE),
815 c->exec_status.start_timestamp.realtime,
816 c->exec_status.start_timestamp.monotonic,
817 c->exec_status.exit_timestamp.realtime,
818 c->exec_status.exit_timestamp.monotonic,
819 (uint32_t) c->exec_status.pid,
820 (int32_t) c->exec_status.code,
821 (int32_t) c->exec_status.status);
822 if (r < 0)
823 return r;
824
825 return sd_bus_message_close_container(reply);
826 }
827
828 int bus_property_get_exec_command(
829 sd_bus *bus,
830 const char *path,
831 const char *interface,
832 const char *property,
833 sd_bus_message *reply,
834 void *userdata,
835 sd_bus_error *ret_error) {
836
837 ExecCommand *c = (ExecCommand*) userdata;
838 int r;
839
840 assert(bus);
841 assert(reply);
842
843 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
844 if (r < 0)
845 return r;
846
847 r = append_exec_command(reply, c);
848 if (r < 0)
849 return r;
850
851 return sd_bus_message_close_container(reply);
852 }
853
854 int bus_property_get_exec_command_list(
855 sd_bus *bus,
856 const char *path,
857 const char *interface,
858 const char *property,
859 sd_bus_message *reply,
860 void *userdata,
861 sd_bus_error *ret_error) {
862
863 ExecCommand *c = *(ExecCommand**) userdata;
864 int r;
865
866 assert(bus);
867 assert(reply);
868
869 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
870 if (r < 0)
871 return r;
872
873 LIST_FOREACH(command, c, c) {
874 r = append_exec_command(reply, c);
875 if (r < 0)
876 return r;
877 }
878
879 return sd_bus_message_close_container(reply);
880 }
881
882 int bus_set_transient_exec_command(
883 Unit *u,
884 const char *name,
885 ExecCommand **exec_command,
886 sd_bus_message *message,
887 UnitWriteFlags flags,
888 sd_bus_error *error) {
889 unsigned n = 0;
890 int r;
891
892 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
893 if (r < 0)
894 return r;
895
896 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
897 _cleanup_strv_free_ char **argv = NULL;
898 const char *path;
899 int b;
900
901 r = sd_bus_message_read(message, "s", &path);
902 if (r < 0)
903 return r;
904
905 if (!path_is_absolute(path))
906 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
907
908 r = sd_bus_message_read_strv(message, &argv);
909 if (r < 0)
910 return r;
911
912 r = sd_bus_message_read(message, "b", &b);
913 if (r < 0)
914 return r;
915
916 r = sd_bus_message_exit_container(message);
917 if (r < 0)
918 return r;
919
920 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
921 ExecCommand *c;
922
923 c = new0(ExecCommand, 1);
924 if (!c)
925 return -ENOMEM;
926
927 c->path = strdup(path);
928 if (!c->path) {
929 free(c);
930 return -ENOMEM;
931 }
932
933 c->argv = TAKE_PTR(argv);
934
935 c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
936
937 path_simplify(c->path, false);
938 exec_command_append_list(exec_command, c);
939 }
940
941 n++;
942 }
943 if (r < 0)
944 return r;
945
946 r = sd_bus_message_exit_container(message);
947 if (r < 0)
948 return r;
949
950 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
951 _cleanup_free_ char *buf = NULL;
952 _cleanup_fclose_ FILE *f = NULL;
953 ExecCommand *c;
954 size_t size = 0;
955
956 if (n == 0)
957 *exec_command = exec_command_free_list(*exec_command);
958
959 f = open_memstream(&buf, &size);
960 if (!f)
961 return -ENOMEM;
962
963 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
964
965 fputs("ExecStart=\n", f);
966
967 LIST_FOREACH(command, c, *exec_command) {
968 _cleanup_free_ char *a = NULL, *t = NULL;
969 const char *p;
970
971 p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
972 if (!p)
973 return -ENOMEM;
974
975 a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
976 if (!a)
977 return -ENOMEM;
978
979 fprintf(f, "%s=%s@%s %s\n",
980 name,
981 c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
982 p,
983 a);
984 }
985
986 r = fflush_and_check(f);
987 if (r < 0)
988 return r;
989
990 unit_write_setting(u, flags, name, buf);
991 }
992
993 return 1;
994 }
995
996 static int parse_personality(const char *s, unsigned long *p) {
997 unsigned long v;
998
999 assert(p);
1000
1001 v = personality_from_string(s);
1002 if (v == PERSONALITY_INVALID)
1003 return -EINVAL;
1004
1005 *p = v;
1006 return 0;
1007 }
1008
1009 static const char* mount_propagation_flags_to_string_with_check(unsigned long n) {
1010 if (!IN_SET(n, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
1011 return NULL;
1012
1013 return mount_propagation_flags_to_string(n);
1014 }
1015
1016 static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT);
1017 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid);
1018 #if HAVE_SECCOMP
1019 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, errno_is_valid);
1020 #endif
1021 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(sched_priority, "i", int32_t, int, "%" PRIi32, sched_priority_is_valid);
1022 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(nice, "i", int32_t, int, "%" PRIi32, nice_is_valid);
1023 static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string);
1024 static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string);
1025 static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_from_string);
1026 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, protect_system_or_bool_from_string);
1027 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, protect_home_or_bool_from_string);
1028 static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string);
1029 static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string);
1030 static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality);
1031 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check);
1032 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint64_t, "%" PRIu64, capability_set_to_string_alloc);
1033 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(sched_policy, "i", int32_t, int, "%" PRIi32, sched_policy_to_string_alloc_with_check);
1034 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flags_to_string);
1035 static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check);
1036
1037 int bus_exec_context_set_transient_property(
1038 Unit *u,
1039 ExecContext *c,
1040 const char *name,
1041 sd_bus_message *message,
1042 UnitWriteFlags flags,
1043 sd_bus_error *error) {
1044
1045 const char *suffix;
1046 int r;
1047
1048 assert(u);
1049 assert(c);
1050 assert(name);
1051 assert(message);
1052
1053 flags |= UNIT_PRIVATE;
1054
1055 if (streq(name, "User"))
1056 return bus_set_transient_user(u, name, &c->user, message, flags, error);
1057
1058 if (streq(name, "Group"))
1059 return bus_set_transient_user(u, name, &c->group, message, flags, error);
1060
1061 if (streq(name, "TTYPath"))
1062 return bus_set_transient_path(u, name, &c->tty_path, message, flags, error);
1063
1064 if (streq(name, "RootImage"))
1065 return bus_set_transient_path(u, name, &c->root_image, message, flags, error);
1066
1067 if (streq(name, "RootDirectory"))
1068 return bus_set_transient_path(u, name, &c->root_directory, message, flags, error);
1069
1070 if (streq(name, "SyslogIdentifier"))
1071 return bus_set_transient_string(u, name, &c->syslog_identifier, message, flags, error);
1072
1073 if (streq(name, "LogLevelMax"))
1074 return bus_set_transient_log_level(u, name, &c->log_level_max, message, flags, error);
1075
1076 if (streq(name, "CPUSchedulingPriority"))
1077 return bus_set_transient_sched_priority(u, name, &c->cpu_sched_priority, message, flags, error);
1078
1079 if (streq(name, "Personality"))
1080 return bus_set_transient_personality(u, name, &c->personality, message, flags, error);
1081
1082 if (streq(name, "Nice"))
1083 return bus_set_transient_nice(u, name, &c->nice, message, flags, error);
1084
1085 if (streq(name, "StandardInput"))
1086 return bus_set_transient_std_input(u, name, &c->std_input, message, flags, error);
1087
1088 if (streq(name, "StandardOutput"))
1089 return bus_set_transient_std_output(u, name, &c->std_output, message, flags, error);
1090
1091 if (streq(name, "StandardError"))
1092 return bus_set_transient_std_output(u, name, &c->std_error, message, flags, error);
1093
1094 if (streq(name, "IgnoreSIGPIPE"))
1095 return bus_set_transient_bool(u, name, &c->ignore_sigpipe, message, flags, error);
1096
1097 if (streq(name, "TTYVHangup"))
1098 return bus_set_transient_bool(u, name, &c->tty_vhangup, message, flags, error);
1099
1100 if (streq(name, "TTYReset"))
1101 return bus_set_transient_bool(u, name, &c->tty_reset, message, flags, error);
1102
1103 if (streq(name, "TTYVTDisallocate"))
1104 return bus_set_transient_bool(u, name, &c->tty_vt_disallocate, message, flags, error);
1105
1106 if (streq(name, "PrivateTmp"))
1107 return bus_set_transient_bool(u, name, &c->private_tmp, message, flags, error);
1108
1109 if (streq(name, "PrivateDevices"))
1110 return bus_set_transient_bool(u, name, &c->private_devices, message, flags, error);
1111
1112 if (streq(name, "PrivateMounts"))
1113 return bus_set_transient_bool(u, name, &c->private_mounts, message, flags, error);
1114
1115 if (streq(name, "PrivateNetwork"))
1116 return bus_set_transient_bool(u, name, &c->private_network, message, flags, error);
1117
1118 if (streq(name, "PrivateUsers"))
1119 return bus_set_transient_bool(u, name, &c->private_users, message, flags, error);
1120
1121 if (streq(name, "NoNewPrivileges"))
1122 return bus_set_transient_bool(u, name, &c->no_new_privileges, message, flags, error);
1123
1124 if (streq(name, "SyslogLevelPrefix"))
1125 return bus_set_transient_bool(u, name, &c->syslog_level_prefix, message, flags, error);
1126
1127 if (streq(name, "MemoryDenyWriteExecute"))
1128 return bus_set_transient_bool(u, name, &c->memory_deny_write_execute, message, flags, error);
1129
1130 if (streq(name, "RestrictRealtime"))
1131 return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error);
1132
1133 if (streq(name, "DynamicUser"))
1134 return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error);
1135
1136 if (streq(name, "RemoveIPC"))
1137 return bus_set_transient_bool(u, name, &c->remove_ipc, message, flags, error);
1138
1139 if (streq(name, "ProtectKernelTunables"))
1140 return bus_set_transient_bool(u, name, &c->protect_kernel_tunables, message, flags, error);
1141
1142 if (streq(name, "ProtectKernelModules"))
1143 return bus_set_transient_bool(u, name, &c->protect_kernel_modules, message, flags, error);
1144
1145 if (streq(name, "ProtectControlGroups"))
1146 return bus_set_transient_bool(u, name, &c->protect_control_groups, message, flags, error);
1147
1148 if (streq(name, "MountAPIVFS"))
1149 return bus_set_transient_bool(u, name, &c->mount_apivfs, message, flags, error);
1150
1151 if (streq(name, "CPUSchedulingResetOnFork"))
1152 return bus_set_transient_bool(u, name, &c->cpu_sched_reset_on_fork, message, flags, error);
1153
1154 if (streq(name, "NonBlocking"))
1155 return bus_set_transient_bool(u, name, &c->non_blocking, message, flags, error);
1156
1157 if (streq(name, "LockPersonality"))
1158 return bus_set_transient_bool(u, name, &c->lock_personality, message, flags, error);
1159
1160 if (streq(name, "UtmpIdentifier"))
1161 return bus_set_transient_string(u, name, &c->utmp_id, message, flags, error);
1162
1163 if (streq(name, "UtmpMode"))
1164 return bus_set_transient_utmp_mode(u, name, &c->utmp_mode, message, flags, error);
1165
1166 if (streq(name, "PAMName"))
1167 return bus_set_transient_string(u, name, &c->pam_name, message, flags, error);
1168
1169 if (streq(name, "TimerSlackNSec"))
1170 return bus_set_transient_nsec(u, name, &c->timer_slack_nsec, message, flags, error);
1171
1172 if (streq(name, "ProtectSystem"))
1173 return bus_set_transient_protect_system(u, name, &c->protect_system, message, flags, error);
1174
1175 if (streq(name, "ProtectHome"))
1176 return bus_set_transient_protect_home(u, name, &c->protect_home, message, flags, error);
1177
1178 if (streq(name, "KeyringMode"))
1179 return bus_set_transient_keyring_mode(u, name, &c->keyring_mode, message, flags, error);
1180
1181 if (streq(name, "RuntimeDirectoryPreserve"))
1182 return bus_set_transient_preserve_mode(u, name, &c->runtime_directory_preserve_mode, message, flags, error);
1183
1184 if (streq(name, "UMask"))
1185 return bus_set_transient_mode_t(u, name, &c->umask, message, flags, error);
1186
1187 if (streq(name, "RuntimeDirectoryMode"))
1188 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_RUNTIME].mode, message, flags, error);
1189
1190 if (streq(name, "StateDirectoryMode"))
1191 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_STATE].mode, message, flags, error);
1192
1193 if (streq(name, "CacheDirectoryMode"))
1194 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CACHE].mode, message, flags, error);
1195
1196 if (streq(name, "LogsDirectoryMode"))
1197 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_LOGS].mode, message, flags, error);
1198
1199 if (streq(name, "ConfigurationDirectoryMode"))
1200 return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CONFIGURATION].mode, message, flags, error);
1201
1202 if (streq(name, "SELinuxContext"))
1203 return bus_set_transient_string(u, name, &c->selinux_context, message, flags, error);
1204
1205 if (streq(name, "SecureBits"))
1206 return bus_set_transient_secure_bits(u, name, &c->secure_bits, message, flags, error);
1207
1208 if (streq(name, "CapabilityBoundingSet"))
1209 return bus_set_transient_capability(u, name, &c->capability_bounding_set, message, flags, error);
1210
1211 if (streq(name, "AmbientCapabilities"))
1212 return bus_set_transient_capability(u, name, &c->capability_ambient_set, message, flags, error);
1213
1214 if (streq(name, "CPUSchedulingPolicy"))
1215 return bus_set_transient_sched_policy(u, name, &c->cpu_sched_policy, message, flags, error);
1216
1217 if (streq(name, "RestrictNamespaces"))
1218 return bus_set_transient_namespace_flag(u, name, &c->restrict_namespaces, message, flags, error);
1219
1220 if (streq(name, "MountFlags"))
1221 return bus_set_transient_mount_flags(u, name, &c->mount_flags, message, flags, error);
1222
1223 if (streq(name, "SupplementaryGroups")) {
1224 _cleanup_strv_free_ char **l = NULL;
1225 char **p;
1226
1227 r = sd_bus_message_read_strv(message, &l);
1228 if (r < 0)
1229 return r;
1230
1231 STRV_FOREACH(p, l) {
1232 if (!isempty(*p) && !valid_user_group_name_or_id(*p))
1233 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid supplementary group names");
1234 }
1235
1236 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1237 if (strv_isempty(l)) {
1238 c->supplementary_groups = strv_free(c->supplementary_groups);
1239 unit_write_settingf(u, flags, name, "%s=", name);
1240 } else {
1241 _cleanup_free_ char *joined = NULL;
1242
1243 r = strv_extend_strv(&c->supplementary_groups, l, true);
1244 if (r < 0)
1245 return -ENOMEM;
1246
1247 joined = strv_join(c->supplementary_groups, " ");
1248 if (!joined)
1249 return -ENOMEM;
1250
1251 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, joined);
1252 }
1253 }
1254
1255 return 1;
1256
1257 } else if (streq(name, "SyslogLevel")) {
1258 int32_t level;
1259
1260 r = sd_bus_message_read(message, "i", &level);
1261 if (r < 0)
1262 return r;
1263
1264 if (!log_level_is_valid(level))
1265 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
1266
1267 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1268 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
1269 unit_write_settingf(u, flags, name, "SyslogLevel=%i", level);
1270 }
1271
1272 return 1;
1273
1274 } else if (streq(name, "SyslogFacility")) {
1275 int32_t facility;
1276
1277 r = sd_bus_message_read(message, "i", &facility);
1278 if (r < 0)
1279 return r;
1280
1281 if (!log_facility_unshifted_is_valid(facility))
1282 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
1283
1284 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1285 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
1286 unit_write_settingf(u, flags, name, "SyslogFacility=%i", facility);
1287 }
1288
1289 return 1;
1290
1291 } else if (streq(name, "LogExtraFields")) {
1292 size_t n = 0;
1293
1294 r = sd_bus_message_enter_container(message, 'a', "ay");
1295 if (r < 0)
1296 return r;
1297
1298 for (;;) {
1299 _cleanup_free_ void *copy = NULL;
1300 struct iovec *t;
1301 const char *eq;
1302 const void *p;
1303 size_t sz;
1304
1305 /* Note that we expect a byte array for each field, instead of a string. That's because on the
1306 * lower-level journal fields can actually contain binary data and are not restricted to text,
1307 * and we should not "lose precision" in our types on the way. That said, I am pretty sure
1308 * actually encoding binary data as unit metadata is not a good idea. Hence we actually refuse
1309 * any actual binary data, and only accept UTF-8. This allows us to eventually lift this
1310 * limitation, should a good, valid usecase arise. */
1311
1312 r = sd_bus_message_read_array(message, 'y', &p, &sz);
1313 if (r < 0)
1314 return r;
1315 if (r == 0)
1316 break;
1317
1318 if (memchr(p, 0, sz))
1319 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains zero byte");
1320
1321 eq = memchr(p, '=', sz);
1322 if (!eq)
1323 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains no '=' character");
1324 if (!journal_field_valid(p, eq - (const char*) p, false))
1325 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field invalid");
1326
1327 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1328 t = reallocarray(c->log_extra_fields, c->n_log_extra_fields+1, sizeof(struct iovec));
1329 if (!t)
1330 return -ENOMEM;
1331 c->log_extra_fields = t;
1332 }
1333
1334 copy = malloc(sz + 1);
1335 if (!copy)
1336 return -ENOMEM;
1337
1338 memcpy(copy, p, sz);
1339 ((uint8_t*) copy)[sz] = 0;
1340
1341 if (!utf8_is_valid(copy))
1342 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field is not valid UTF-8");
1343
1344 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1345 c->log_extra_fields[c->n_log_extra_fields++] = IOVEC_MAKE(copy, sz);
1346 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C, name, "LogExtraFields=%s", (char*) copy);
1347
1348 copy = NULL;
1349 }
1350
1351 n++;
1352 }
1353
1354 r = sd_bus_message_exit_container(message);
1355 if (r < 0)
1356 return r;
1357
1358 if (!UNIT_WRITE_FLAGS_NOOP(flags) && n == 0) {
1359 exec_context_free_log_extra_fields(c);
1360 unit_write_setting(u, flags, name, "LogExtraFields=");
1361 }
1362
1363 return 1;
1364 }
1365
1366 #if HAVE_SECCOMP
1367
1368 if (streq(name, "SystemCallErrorNumber"))
1369 return bus_set_transient_errno(u, name, &c->syscall_errno, message, flags, error);
1370
1371 if (streq(name, "SystemCallFilter")) {
1372 int whitelist;
1373 _cleanup_strv_free_ char **l = NULL;
1374
1375 r = sd_bus_message_enter_container(message, 'r', "bas");
1376 if (r < 0)
1377 return r;
1378
1379 r = sd_bus_message_read(message, "b", &whitelist);
1380 if (r < 0)
1381 return r;
1382
1383 r = sd_bus_message_read_strv(message, &l);
1384 if (r < 0)
1385 return r;
1386
1387 r = sd_bus_message_exit_container(message);
1388 if (r < 0)
1389 return r;
1390
1391 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1392 _cleanup_free_ char *joined = NULL;
1393 bool invert = !whitelist;
1394 char **s;
1395
1396 if (strv_isempty(l)) {
1397 c->syscall_whitelist = false;
1398 c->syscall_filter = hashmap_free(c->syscall_filter);
1399
1400 unit_write_settingf(u, flags, name, "SystemCallFilter=");
1401 return 1;
1402 }
1403
1404 if (!c->syscall_filter) {
1405 c->syscall_filter = hashmap_new(NULL);
1406 if (!c->syscall_filter)
1407 return log_oom();
1408
1409 c->syscall_whitelist = whitelist;
1410
1411 if (c->syscall_whitelist) {
1412 r = seccomp_parse_syscall_filter("@default", -1, c->syscall_filter, SECCOMP_PARSE_WHITELIST | (invert ? SECCOMP_PARSE_INVERT : 0));
1413 if (r < 0)
1414 return r;
1415 }
1416 }
1417
1418 STRV_FOREACH(s, l) {
1419 _cleanup_free_ char *n = NULL;
1420 int e;
1421
1422 r = parse_syscall_and_errno(*s, &n, &e);
1423 if (r < 0)
1424 return r;
1425
1426 r = seccomp_parse_syscall_filter(n, e, c->syscall_filter, (invert ? SECCOMP_PARSE_INVERT : 0) | (c->syscall_whitelist ? SECCOMP_PARSE_WHITELIST : 0));
1427 if (r < 0)
1428 return r;
1429 }
1430
1431 joined = strv_join(l, " ");
1432 if (!joined)
1433 return -ENOMEM;
1434
1435 unit_write_settingf(u, flags, name, "SystemCallFilter=%s%s", whitelist ? "" : "~", joined);
1436 }
1437
1438 return 1;
1439
1440 } else if (streq(name, "SystemCallArchitectures")) {
1441 _cleanup_strv_free_ char **l = NULL;
1442
1443 r = sd_bus_message_read_strv(message, &l);
1444 if (r < 0)
1445 return r;
1446
1447 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1448 _cleanup_free_ char *joined = NULL;
1449
1450 if (strv_isempty(l))
1451 c->syscall_archs = set_free(c->syscall_archs);
1452 else {
1453 char **s;
1454
1455 r = set_ensure_allocated(&c->syscall_archs, NULL);
1456 if (r < 0)
1457 return r;
1458
1459 STRV_FOREACH(s, l) {
1460 uint32_t a;
1461
1462 r = seccomp_arch_from_string(*s, &a);
1463 if (r < 0)
1464 return r;
1465
1466 r = set_put(c->syscall_archs, UINT32_TO_PTR(a + 1));
1467 if (r < 0)
1468 return r;
1469 }
1470
1471 }
1472
1473 joined = strv_join(l, " ");
1474 if (!joined)
1475 return -ENOMEM;
1476
1477 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
1478 }
1479
1480 return 1;
1481
1482 } else if (streq(name, "RestrictAddressFamilies")) {
1483 int whitelist;
1484 _cleanup_strv_free_ char **l = NULL;
1485
1486 r = sd_bus_message_enter_container(message, 'r', "bas");
1487 if (r < 0)
1488 return r;
1489
1490 r = sd_bus_message_read(message, "b", &whitelist);
1491 if (r < 0)
1492 return r;
1493
1494 r = sd_bus_message_read_strv(message, &l);
1495 if (r < 0)
1496 return r;
1497
1498 r = sd_bus_message_exit_container(message);
1499 if (r < 0)
1500 return r;
1501
1502 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1503 _cleanup_free_ char *joined = NULL;
1504 bool invert = !whitelist;
1505 char **s;
1506
1507 if (strv_isempty(l)) {
1508 c->address_families_whitelist = false;
1509 c->address_families = set_free(c->address_families);
1510
1511 unit_write_settingf(u, flags, name, "RestrictAddressFamilies=");
1512 return 1;
1513 }
1514
1515 if (!c->address_families) {
1516 c->address_families = set_new(NULL);
1517 if (!c->address_families)
1518 return log_oom();
1519
1520 c->address_families_whitelist = whitelist;
1521 }
1522
1523 STRV_FOREACH(s, l) {
1524 int af;
1525
1526 af = af_from_name(*s);
1527 if (af <= 0)
1528 return -EINVAL;
1529
1530 if (!invert == c->address_families_whitelist) {
1531 r = set_put(c->address_families, INT_TO_PTR(af));
1532 if (r < 0)
1533 return r;
1534 } else
1535 (void) set_remove(c->address_families, INT_TO_PTR(af));
1536 }
1537
1538 joined = strv_join(l, " ");
1539 if (!joined)
1540 return -ENOMEM;
1541
1542 unit_write_settingf(u, flags, name, "RestrictAddressFamilies=%s%s", whitelist ? "" : "~", joined);
1543 }
1544
1545 return 1;
1546 }
1547 #endif
1548 if (streq(name, "CPUAffinity")) {
1549 const void *a;
1550 size_t n = 0;
1551
1552 r = sd_bus_message_read_array(message, 'y', &a, &n);
1553 if (r < 0)
1554 return r;
1555
1556 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1557 if (n == 0) {
1558 c->cpuset = cpu_set_mfree(c->cpuset);
1559 c->cpuset_ncpus = 0;
1560 unit_write_settingf(u, flags, name, "%s=", name);
1561 } else {
1562 _cleanup_free_ char *str = NULL;
1563 size_t allocated = 0, len = 0, i, ncpus;
1564
1565 ncpus = CPU_SIZE_TO_NUM(n);
1566
1567 for (i = 0; i < ncpus; i++) {
1568 _cleanup_free_ char *p = NULL;
1569 size_t add;
1570
1571 if (!CPU_ISSET_S(i, n, (cpu_set_t*) a))
1572 continue;
1573
1574 r = asprintf(&p, "%zu", i);
1575 if (r < 0)
1576 return -ENOMEM;
1577
1578 add = strlen(p);
1579
1580 if (!GREEDY_REALLOC(str, allocated, len + add + 2))
1581 return -ENOMEM;
1582
1583 strcpy(mempcpy(str + len, p, add), " ");
1584 len += add + 1;
1585 }
1586
1587 if (len != 0)
1588 str[len - 1] = '\0';
1589
1590 if (!c->cpuset || c->cpuset_ncpus < ncpus) {
1591 cpu_set_t *cpuset;
1592
1593 cpuset = CPU_ALLOC(ncpus);
1594 if (!cpuset)
1595 return -ENOMEM;
1596
1597 CPU_ZERO_S(n, cpuset);
1598 if (c->cpuset) {
1599 CPU_OR_S(CPU_ALLOC_SIZE(c->cpuset_ncpus), cpuset, c->cpuset, (cpu_set_t*) a);
1600 CPU_FREE(c->cpuset);
1601 } else
1602 CPU_OR_S(n, cpuset, cpuset, (cpu_set_t*) a);
1603
1604 c->cpuset = cpuset;
1605 c->cpuset_ncpus = ncpus;
1606 } else
1607 CPU_OR_S(n, c->cpuset, c->cpuset, (cpu_set_t*) a);
1608
1609 unit_write_settingf(u, flags, name, "%s=%s", name, str);
1610 }
1611 }
1612
1613 return 1;
1614
1615 } else if (streq(name, "IOSchedulingClass")) {
1616 int32_t q;
1617
1618 r = sd_bus_message_read(message, "i", &q);
1619 if (r < 0)
1620 return r;
1621
1622 if (!ioprio_class_is_valid(q))
1623 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q);
1624
1625 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1626 _cleanup_free_ char *s = NULL;
1627
1628 r = ioprio_class_to_string_alloc(q, &s);
1629 if (r < 0)
1630 return r;
1631
1632 c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio));
1633 c->ioprio_set = true;
1634
1635 unit_write_settingf(u, flags, name, "IOSchedulingClass=%s", s);
1636 }
1637
1638 return 1;
1639
1640 } else if (streq(name, "IOSchedulingPriority")) {
1641 int32_t p;
1642
1643 r = sd_bus_message_read(message, "i", &p);
1644 if (r < 0)
1645 return r;
1646
1647 if (!ioprio_priority_is_valid(p))
1648 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
1649
1650 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1651 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p);
1652 c->ioprio_set = true;
1653
1654 unit_write_settingf(u, flags, name, "IOSchedulingPriority=%i", p);
1655 }
1656
1657 return 1;
1658
1659 } else if (streq(name, "WorkingDirectory")) {
1660 const char *s;
1661 bool missing_ok;
1662
1663 r = sd_bus_message_read(message, "s", &s);
1664 if (r < 0)
1665 return r;
1666
1667 if (s[0] == '-') {
1668 missing_ok = true;
1669 s++;
1670 } else
1671 missing_ok = false;
1672
1673 if (!isempty(s) && !streq(s, "~") && !path_is_absolute(s))
1674 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
1675
1676 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1677 if (streq(s, "~")) {
1678 c->working_directory = mfree(c->working_directory);
1679 c->working_directory_home = true;
1680 } else {
1681 r = free_and_strdup(&c->working_directory, empty_to_null(s));
1682 if (r < 0)
1683 return r;
1684
1685 c->working_directory_home = false;
1686 }
1687
1688 c->working_directory_missing_ok = missing_ok;
1689 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
1690 }
1691
1692 return 1;
1693
1694 } else if (STR_IN_SET(name,
1695 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
1696 const char *s;
1697
1698 r = sd_bus_message_read(message, "s", &s);
1699 if (r < 0)
1700 return r;
1701
1702 if (!isempty(s) && !fdname_is_valid(s))
1703 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
1704
1705 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1706
1707 if (streq(name, "StandardInputFileDescriptorName")) {
1708 r = free_and_strdup(c->stdio_fdname + STDIN_FILENO, empty_to_null(s));
1709 if (r < 0)
1710 return r;
1711
1712 c->std_input = EXEC_INPUT_NAMED_FD;
1713 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=fd:%s", exec_context_fdname(c, STDIN_FILENO));
1714
1715 } else if (streq(name, "StandardOutputFileDescriptorName")) {
1716 r = free_and_strdup(c->stdio_fdname + STDOUT_FILENO, empty_to_null(s));
1717 if (r < 0)
1718 return r;
1719
1720 c->std_output = EXEC_OUTPUT_NAMED_FD;
1721 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=fd:%s", exec_context_fdname(c, STDOUT_FILENO));
1722
1723 } else {
1724 assert(streq(name, "StandardErrorFileDescriptorName"));
1725
1726 r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], empty_to_null(s));
1727 if (r < 0)
1728 return r;
1729
1730 c->std_error = EXEC_OUTPUT_NAMED_FD;
1731 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=fd:%s", exec_context_fdname(c, STDERR_FILENO));
1732 }
1733 }
1734
1735 return 1;
1736
1737 } else if (STR_IN_SET(name, "StandardInputFile", "StandardOutputFile", "StandardErrorFile")) {
1738 const char *s;
1739
1740 r = sd_bus_message_read(message, "s", &s);
1741 if (r < 0)
1742 return r;
1743
1744 if (!isempty(s)) {
1745 if (!path_is_absolute(s))
1746 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute", s);
1747 if (!path_is_normalized(s))
1748 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", s);
1749 }
1750
1751 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1752
1753 if (streq(name, "StandardInputFile")) {
1754 r = free_and_strdup(&c->stdio_file[STDIN_FILENO], empty_to_null(s));
1755 if (r < 0)
1756 return r;
1757
1758 c->std_input = EXEC_INPUT_FILE;
1759 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s);
1760
1761 } else if (streq(name, "StandardOutputFile")) {
1762 r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], empty_to_null(s));
1763 if (r < 0)
1764 return r;
1765
1766 c->std_output = EXEC_OUTPUT_FILE;
1767 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
1768
1769 } else {
1770 assert(streq(name, "StandardErrorFile"));
1771
1772 r = free_and_strdup(&c->stdio_file[STDERR_FILENO], empty_to_null(s));
1773 if (r < 0)
1774 return r;
1775
1776 c->std_error = EXEC_OUTPUT_FILE;
1777 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s);
1778 }
1779 }
1780
1781 return 1;
1782
1783 } else if (streq(name, "StandardInputData")) {
1784 const void *p;
1785 size_t sz;
1786
1787 r = sd_bus_message_read_array(message, 'y', &p, &sz);
1788 if (r < 0)
1789 return r;
1790
1791 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1792 _cleanup_free_ char *encoded = NULL;
1793
1794 if (sz == 0) {
1795 c->stdin_data = mfree(c->stdin_data);
1796 c->stdin_data_size = 0;
1797
1798 unit_write_settingf(u, flags, name, "StandardInputData=");
1799 } else {
1800 void *q;
1801 ssize_t n;
1802
1803 if (c->stdin_data_size + sz < c->stdin_data_size || /* check for overflow */
1804 c->stdin_data_size + sz > EXEC_STDIN_DATA_MAX)
1805 return -E2BIG;
1806
1807 n = base64mem(p, sz, &encoded);
1808 if (n < 0)
1809 return (int) n;
1810
1811 q = realloc(c->stdin_data, c->stdin_data_size + sz);
1812 if (!q)
1813 return -ENOMEM;
1814
1815 memcpy((uint8_t*) q + c->stdin_data_size, p, sz);
1816
1817 c->stdin_data = q;
1818 c->stdin_data_size += sz;
1819
1820 unit_write_settingf(u, flags, name, "StandardInputData=%s", encoded);
1821 }
1822 }
1823
1824 return 1;
1825
1826 } else if (streq(name, "Environment")) {
1827
1828 _cleanup_strv_free_ char **l = NULL;
1829
1830 r = sd_bus_message_read_strv(message, &l);
1831 if (r < 0)
1832 return r;
1833
1834 if (!strv_env_is_valid(l))
1835 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1836
1837 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1838 if (strv_isempty(l)) {
1839 c->environment = strv_free(c->environment);
1840 unit_write_setting(u, flags, name, "Environment=");
1841 } else {
1842 _cleanup_free_ char *joined = NULL;
1843 char **e;
1844
1845 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
1846 if (!joined)
1847 return -ENOMEM;
1848
1849 e = strv_env_merge(2, c->environment, l);
1850 if (!e)
1851 return -ENOMEM;
1852
1853 strv_free_and_replace(c->environment, e);
1854 unit_write_settingf(u, flags, name, "Environment=%s", joined);
1855 }
1856 }
1857
1858 return 1;
1859
1860 } else if (streq(name, "UnsetEnvironment")) {
1861
1862 _cleanup_strv_free_ char **l = NULL;
1863
1864 r = sd_bus_message_read_strv(message, &l);
1865 if (r < 0)
1866 return r;
1867
1868 if (!strv_env_name_or_assignment_is_valid(l))
1869 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list.");
1870
1871 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1872 if (strv_isempty(l)) {
1873 c->unset_environment = strv_free(c->unset_environment);
1874 unit_write_setting(u, flags, name, "UnsetEnvironment=");
1875 } else {
1876 _cleanup_free_ char *joined = NULL;
1877 char **e;
1878
1879 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
1880 if (!joined)
1881 return -ENOMEM;
1882
1883 e = strv_env_merge(2, c->unset_environment, l);
1884 if (!e)
1885 return -ENOMEM;
1886
1887 strv_free_and_replace(c->unset_environment, e);
1888 unit_write_settingf(u, flags, name, "UnsetEnvironment=%s", joined);
1889 }
1890 }
1891
1892 return 1;
1893
1894 } else if (streq(name, "OOMScoreAdjust")) {
1895 int oa;
1896
1897 r = sd_bus_message_read(message, "i", &oa);
1898 if (r < 0)
1899 return r;
1900
1901 if (!oom_score_adjust_is_valid(oa))
1902 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
1903
1904 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1905 c->oom_score_adjust = oa;
1906 c->oom_score_adjust_set = true;
1907 unit_write_settingf(u, flags, name, "OOMScoreAdjust=%i", oa);
1908 }
1909
1910 return 1;
1911
1912 } else if (streq(name, "EnvironmentFiles")) {
1913
1914 _cleanup_free_ char *joined = NULL;
1915 _cleanup_fclose_ FILE *f = NULL;
1916 _cleanup_strv_free_ char **l = NULL;
1917 size_t size = 0;
1918 char **i;
1919
1920 r = sd_bus_message_enter_container(message, 'a', "(sb)");
1921 if (r < 0)
1922 return r;
1923
1924 f = open_memstream(&joined, &size);
1925 if (!f)
1926 return -ENOMEM;
1927
1928 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1929
1930 fputs("EnvironmentFile=\n", f);
1931
1932 STRV_FOREACH(i, c->environment_files) {
1933 _cleanup_free_ char *q = NULL;
1934
1935 q = specifier_escape(*i);
1936 if (!q)
1937 return -ENOMEM;
1938
1939 fprintf(f, "EnvironmentFile=%s\n", q);
1940 }
1941
1942 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
1943 const char *path;
1944 int b;
1945
1946 r = sd_bus_message_read(message, "sb", &path, &b);
1947 if (r < 0)
1948 return r;
1949
1950 r = sd_bus_message_exit_container(message);
1951 if (r < 0)
1952 return r;
1953
1954 if (!path_is_absolute(path))
1955 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
1956
1957 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1958 _cleanup_free_ char *q = NULL;
1959 char *buf;
1960
1961 buf = strjoin(b ? "-" : "", path);
1962 if (!buf)
1963 return -ENOMEM;
1964
1965 q = specifier_escape(buf);
1966 if (!q) {
1967 free(buf);
1968 return -ENOMEM;
1969 }
1970
1971 fprintf(f, "EnvironmentFile=%s\n", q);
1972
1973 r = strv_consume(&l, buf);
1974 if (r < 0)
1975 return r;
1976 }
1977 }
1978 if (r < 0)
1979 return r;
1980
1981 r = sd_bus_message_exit_container(message);
1982 if (r < 0)
1983 return r;
1984
1985 r = fflush_and_check(f);
1986 if (r < 0)
1987 return r;
1988
1989 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1990 if (strv_isempty(l)) {
1991 c->environment_files = strv_free(c->environment_files);
1992 unit_write_setting(u, flags, name, "EnvironmentFile=");
1993 } else {
1994 r = strv_extend_strv(&c->environment_files, l, true);
1995 if (r < 0)
1996 return r;
1997
1998 unit_write_setting(u, flags, name, joined);
1999 }
2000 }
2001
2002 return 1;
2003
2004 } else if (streq(name, "PassEnvironment")) {
2005
2006 _cleanup_strv_free_ char **l = NULL;
2007
2008 r = sd_bus_message_read_strv(message, &l);
2009 if (r < 0)
2010 return r;
2011
2012 if (!strv_env_name_is_valid(l))
2013 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block.");
2014
2015 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2016 if (strv_isempty(l)) {
2017 c->pass_environment = strv_free(c->pass_environment);
2018 unit_write_setting(u, flags, name, "PassEnvironment=");
2019 } else {
2020 _cleanup_free_ char *joined = NULL;
2021
2022 r = strv_extend_strv(&c->pass_environment, l, true);
2023 if (r < 0)
2024 return r;
2025
2026 /* We write just the new settings out to file, with unresolved specifiers. */
2027 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
2028 if (!joined)
2029 return -ENOMEM;
2030
2031 unit_write_settingf(u, flags, name, "PassEnvironment=%s", joined);
2032 }
2033 }
2034
2035 return 1;
2036
2037 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
2038 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) {
2039 _cleanup_strv_free_ char **l = NULL;
2040 char ***dirs;
2041 char **p;
2042
2043 r = sd_bus_message_read_strv(message, &l);
2044 if (r < 0)
2045 return r;
2046
2047 STRV_FOREACH(p, l) {
2048 char *i = *p;
2049 size_t offset;
2050
2051 offset = i[0] == '-';
2052 offset += i[offset] == '+';
2053 if (!path_is_absolute(i + offset))
2054 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
2055
2056 path_simplify(i + offset, false);
2057 }
2058
2059 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2060 if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths"))
2061 dirs = &c->read_write_paths;
2062 else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
2063 dirs = &c->read_only_paths;
2064 else /* "InaccessiblePaths" */
2065 dirs = &c->inaccessible_paths;
2066
2067 if (strv_isempty(l)) {
2068 *dirs = strv_free(*dirs);
2069 unit_write_settingf(u, flags, name, "%s=", name);
2070 } else {
2071 _cleanup_free_ char *joined = NULL;
2072
2073 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
2074 if (!joined)
2075 return -ENOMEM;
2076
2077 r = strv_extend_strv(dirs, l, true);
2078 if (r < 0)
2079 return -ENOMEM;
2080
2081 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
2082 }
2083 }
2084
2085 return 1;
2086
2087 } else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
2088 _cleanup_strv_free_ char **l = NULL;
2089 char **p;
2090
2091 r = sd_bus_message_read_strv(message, &l);
2092 if (r < 0)
2093 return r;
2094
2095 STRV_FOREACH(p, l) {
2096 if (!path_is_normalized(*p))
2097 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not normalized: %s", name, *p);
2098
2099 if (path_is_absolute(*p))
2100 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is absolute: %s", name, *p);
2101
2102 if (path_startswith(*p, "private"))
2103 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path can't be 'private': %s", name, *p);
2104 }
2105
2106 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2107 char ***dirs = NULL;
2108 ExecDirectoryType i;
2109
2110 for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++)
2111 if (streq(name, exec_directory_type_to_string(i))) {
2112 dirs = &c->directories[i].paths;
2113 break;
2114 }
2115
2116 assert(dirs);
2117
2118 if (strv_isempty(l)) {
2119 *dirs = strv_free(*dirs);
2120 unit_write_settingf(u, flags, name, "%s=", name);
2121 } else {
2122 _cleanup_free_ char *joined = NULL;
2123
2124 r = strv_extend_strv(dirs, l, true);
2125 if (r < 0)
2126 return -ENOMEM;
2127
2128 joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
2129 if (!joined)
2130 return -ENOMEM;
2131
2132 unit_write_settingf(u, flags, name, "%s=%s", name, joined);
2133 }
2134 }
2135
2136 return 1;
2137
2138 } else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
2139 int ignore;
2140 const char *s;
2141
2142 r = sd_bus_message_read(message, "(bs)", &ignore, &s);
2143 if (r < 0)
2144 return r;
2145
2146 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2147 char **p;
2148 bool *b;
2149
2150 if (streq(name, "AppArmorProfile")) {
2151 p = &c->apparmor_profile;
2152 b = &c->apparmor_profile_ignore;
2153 } else { /* "SmackProcessLabel" */
2154 p = &c->smack_process_label;
2155 b = &c->smack_process_label_ignore;
2156 }
2157
2158 if (isempty(s)) {
2159 *p = mfree(*p);
2160 *b = false;
2161 } else {
2162 if (free_and_strdup(p, s) < 0)
2163 return -ENOMEM;
2164 *b = ignore;
2165 }
2166
2167 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
2168 }
2169
2170 return 1;
2171
2172 } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
2173 const char *source, *destination;
2174 int ignore_enoent;
2175 uint64_t mount_flags;
2176 bool empty = true;
2177
2178 r = sd_bus_message_enter_container(message, 'a', "(ssbt)");
2179 if (r < 0)
2180 return r;
2181
2182 while ((r = sd_bus_message_read(message, "(ssbt)", &source, &destination, &ignore_enoent, &mount_flags)) > 0) {
2183
2184 if (!path_is_absolute(source))
2185 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
2186 if (!path_is_absolute(destination))
2187 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
2188 if (!IN_SET(mount_flags, 0, MS_REC))
2189 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
2190
2191 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2192 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
2193 &(BindMount) {
2194 .source = strdup(source),
2195 .destination = strdup(destination),
2196 .read_only = !!strstr(name, "ReadOnly"),
2197 .recursive = !!(mount_flags & MS_REC),
2198 .ignore_enoent = ignore_enoent,
2199 });
2200 if (r < 0)
2201 return r;
2202
2203 unit_write_settingf(
2204 u, flags|UNIT_ESCAPE_SPECIFIERS, name,
2205 "%s=%s%s:%s:%s",
2206 name,
2207 ignore_enoent ? "-" : "",
2208 source,
2209 destination,
2210 (mount_flags & MS_REC) ? "rbind" : "norbind");
2211 }
2212
2213 empty = false;
2214 }
2215 if (r < 0)
2216 return r;
2217
2218 r = sd_bus_message_exit_container(message);
2219 if (r < 0)
2220 return r;
2221
2222 if (empty) {
2223 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
2224 c->bind_mounts = NULL;
2225 c->n_bind_mounts = 0;
2226
2227 unit_write_settingf(u, flags, name, "%s=", name);
2228 }
2229
2230 return 1;
2231
2232 } else if (streq(name, "TemporaryFileSystem")) {
2233 const char *path, *options;
2234 bool empty = true;
2235
2236 r = sd_bus_message_enter_container(message, 'a', "(ss)");
2237 if (r < 0)
2238 return r;
2239
2240 while ((r = sd_bus_message_read(message, "(ss)", &path, &options)) > 0) {
2241
2242 if (!path_is_absolute(path))
2243 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Mount point %s is not absolute.", path);
2244
2245 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2246 r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, path, options);
2247 if (r < 0)
2248 return r;
2249
2250 unit_write_settingf(
2251 u, flags|UNIT_ESCAPE_SPECIFIERS, name,
2252 "%s=%s:%s",
2253 name,
2254 path,
2255 options);
2256 }
2257
2258 empty = false;
2259 }
2260 if (r < 0)
2261 return r;
2262
2263 r = sd_bus_message_exit_container(message);
2264 if (r < 0)
2265 return r;
2266
2267 if (empty) {
2268 temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems);
2269 c->temporary_filesystems = NULL;
2270 c->n_temporary_filesystems = 0;
2271
2272 unit_write_settingf(u, flags, name, "%s=", name);
2273 }
2274
2275 return 1;
2276
2277 } else if ((suffix = startswith(name, "Limit"))) {
2278 const char *soft = NULL;
2279 int ri;
2280
2281 ri = rlimit_from_string(suffix);
2282 if (ri < 0) {
2283 soft = endswith(suffix, "Soft");
2284 if (soft) {
2285 const char *n;
2286
2287 n = strndupa(suffix, soft - suffix);
2288 ri = rlimit_from_string(n);
2289 if (ri >= 0)
2290 name = strjoina("Limit", n);
2291 }
2292 }
2293
2294 if (ri >= 0) {
2295 uint64_t rl;
2296 rlim_t x;
2297
2298 r = sd_bus_message_read(message, "t", &rl);
2299 if (r < 0)
2300 return r;
2301
2302 if (rl == (uint64_t) -1)
2303 x = RLIM_INFINITY;
2304 else {
2305 x = (rlim_t) rl;
2306
2307 if ((uint64_t) x != rl)
2308 return -ERANGE;
2309 }
2310
2311 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2312 _cleanup_free_ char *f = NULL;
2313 struct rlimit nl;
2314
2315 if (c->rlimit[ri]) {
2316 nl = *c->rlimit[ri];
2317
2318 if (soft)
2319 nl.rlim_cur = x;
2320 else
2321 nl.rlim_max = x;
2322 } else
2323 /* When the resource limit is not initialized yet, then assign the value to both fields */
2324 nl = (struct rlimit) {
2325 .rlim_cur = x,
2326 .rlim_max = x,
2327 };
2328
2329 r = rlimit_format(&nl, &f);
2330 if (r < 0)
2331 return r;
2332
2333 if (c->rlimit[ri])
2334 *c->rlimit[ri] = nl;
2335 else {
2336 c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
2337 if (!c->rlimit[ri])
2338 return -ENOMEM;
2339 }
2340
2341 unit_write_settingf(u, flags, name, "%s=%s", name, f);
2342 }
2343
2344 return 1;
2345 }
2346
2347 }
2348
2349 return 0;
2350 }