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