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