1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
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.
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.
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/>.
21 #include <sys/prctl.h>
22 #include <stdio_ext.h>
29 #include "alloc-util.h"
32 #include "capability-util.h"
33 #include "cpu-set-util.h"
34 #include "dbus-execute.h"
36 #include "errno-list.h"
41 #include "hexdecoct.h"
44 #include "journal-util.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"
53 #include "seccomp-util.h"
55 #include "securebits-util.h"
56 #include "specifier.h"
58 #include "syslog-util.h"
59 #include "unit-printf.h"
60 #include "user-util.h"
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
);
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
);
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
);
73 static int property_get_environment_files(
76 const char *interface
,
78 sd_bus_message
*reply
,
80 sd_bus_error
*error
) {
82 ExecContext
*c
= userdata
;
90 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
94 STRV_FOREACH(j
, c
->environment_files
) {
97 r
= sd_bus_message_append(reply
, "(sb)", fn
[0] == '-' ? fn
+ 1 : fn
, fn
[0] == '-');
102 return sd_bus_message_close_container(reply
);
105 static int property_get_oom_score_adjust(
108 const char *interface
,
109 const char *property
,
110 sd_bus_message
*reply
,
112 sd_bus_error
*error
) {
115 ExecContext
*c
= userdata
;
122 if (c
->oom_score_adjust_set
)
123 n
= c
->oom_score_adjust
;
125 _cleanup_free_
char *t
= NULL
;
128 if (read_one_line_file("/proc/self/oom_score_adj", &t
) >= 0)
132 return sd_bus_message_append(reply
, "i", n
);
135 static int property_get_nice(
138 const char *interface
,
139 const char *property
,
140 sd_bus_message
*reply
,
142 sd_bus_error
*error
) {
145 ExecContext
*c
= userdata
;
156 n
= getpriority(PRIO_PROCESS
, 0);
161 return sd_bus_message_append(reply
, "i", n
);
164 static int property_get_ioprio(
167 const char *interface
,
168 const char *property
,
169 sd_bus_message
*reply
,
171 sd_bus_error
*error
) {
174 ExecContext
*c
= userdata
;
180 return sd_bus_message_append(reply
, "i", exec_context_get_effective_ioprio(c
));
183 static int property_get_ioprio_class(
186 const char *interface
,
187 const char *property
,
188 sd_bus_message
*reply
,
190 sd_bus_error
*error
) {
193 ExecContext
*c
= userdata
;
199 return sd_bus_message_append(reply
, "i", IOPRIO_PRIO_CLASS(exec_context_get_effective_ioprio(c
)));
202 static int property_get_ioprio_priority(
205 const char *interface
,
206 const char *property
,
207 sd_bus_message
*reply
,
209 sd_bus_error
*error
) {
212 ExecContext
*c
= userdata
;
218 return sd_bus_message_append(reply
, "i", IOPRIO_PRIO_DATA(exec_context_get_effective_ioprio(c
)));
221 static int property_get_cpu_sched_policy(
224 const char *interface
,
225 const char *property
,
226 sd_bus_message
*reply
,
228 sd_bus_error
*error
) {
230 ExecContext
*c
= userdata
;
237 if (c
->cpu_sched_set
)
238 n
= c
->cpu_sched_policy
;
240 n
= sched_getscheduler(0);
245 return sd_bus_message_append(reply
, "i", n
);
248 static int property_get_cpu_sched_priority(
251 const char *interface
,
252 const char *property
,
253 sd_bus_message
*reply
,
255 sd_bus_error
*error
) {
257 ExecContext
*c
= userdata
;
264 if (c
->cpu_sched_set
)
265 n
= c
->cpu_sched_priority
;
267 struct sched_param p
= {};
269 if (sched_getparam(0, &p
) >= 0)
270 n
= p
.sched_priority
;
275 return sd_bus_message_append(reply
, "i", n
);
278 static int property_get_cpu_affinity(
281 const char *interface
,
282 const char *property
,
283 sd_bus_message
*reply
,
285 sd_bus_error
*error
) {
287 ExecContext
*c
= userdata
;
294 return sd_bus_message_append_array(reply
, 'y', c
->cpuset
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
));
296 return sd_bus_message_append_array(reply
, 'y', NULL
, 0);
299 static int property_get_timer_slack_nsec(
302 const char *interface
,
303 const char *property
,
304 sd_bus_message
*reply
,
306 sd_bus_error
*error
) {
308 ExecContext
*c
= userdata
;
315 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
316 u
= (uint64_t) c
->timer_slack_nsec
;
318 u
= (uint64_t) prctl(PR_GET_TIMERSLACK
);
320 return sd_bus_message_append(reply
, "t", u
);
323 static int property_get_capability_bounding_set(
326 const char *interface
,
327 const char *property
,
328 sd_bus_message
*reply
,
330 sd_bus_error
*error
) {
332 ExecContext
*c
= userdata
;
338 return sd_bus_message_append(reply
, "t", c
->capability_bounding_set
);
341 static int property_get_ambient_capabilities(
344 const char *interface
,
345 const char *property
,
346 sd_bus_message
*reply
,
348 sd_bus_error
*error
) {
350 ExecContext
*c
= userdata
;
356 return sd_bus_message_append(reply
, "t", c
->capability_ambient_set
);
359 static int property_get_empty_string(
362 const char *interface
,
363 const char *property
,
364 sd_bus_message
*reply
,
366 sd_bus_error
*error
) {
371 return sd_bus_message_append(reply
, "s", "");
374 static int property_get_syscall_filter(
377 const char *interface
,
378 const char *property
,
379 sd_bus_message
*reply
,
381 sd_bus_error
*error
) {
383 ExecContext
*c
= userdata
;
384 _cleanup_strv_free_
char **l
= NULL
;
396 r
= sd_bus_message_open_container(reply
, 'r', "bas");
400 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
405 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_filter
, i
) {
406 _cleanup_free_
char *name
= NULL
;
407 const char *e
= NULL
;
409 int num
= PTR_TO_INT(val
);
411 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
416 e
= errno_to_name(num
);
418 s
= strjoin(name
, ":", e
);
422 r
= asprintf(&s
, "%s:%d", name
, num
);
431 r
= strv_consume(&l
, s
);
439 r
= sd_bus_message_append_strv(reply
, l
);
443 return sd_bus_message_close_container(reply
);
446 static int property_get_syscall_archs(
449 const char *interface
,
450 const char *property
,
451 sd_bus_message
*reply
,
453 sd_bus_error
*error
) {
455 ExecContext
*c
= userdata
;
456 _cleanup_strv_free_
char **l
= NULL
;
469 SET_FOREACH(id
, c
->syscall_archs
, i
) {
472 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
476 r
= strv_extend(&l
, name
);
484 r
= sd_bus_message_append_strv(reply
, l
);
491 static int property_get_syscall_errno(
494 const char *interface
,
495 const char *property
,
496 sd_bus_message
*reply
,
498 sd_bus_error
*error
) {
500 ExecContext
*c
= userdata
;
506 return sd_bus_message_append(reply
, "i", (int32_t) c
->syscall_errno
);
509 static int property_get_selinux_context(
512 const char *interface
,
513 const char *property
,
514 sd_bus_message
*reply
,
516 sd_bus_error
*error
) {
518 ExecContext
*c
= userdata
;
524 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
527 static int property_get_apparmor_profile(
530 const char *interface
,
531 const char *property
,
532 sd_bus_message
*reply
,
534 sd_bus_error
*error
) {
536 ExecContext
*c
= userdata
;
542 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
545 static int property_get_smack_process_label(
548 const char *interface
,
549 const char *property
,
550 sd_bus_message
*reply
,
552 sd_bus_error
*error
) {
554 ExecContext
*c
= userdata
;
560 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
563 static int property_get_personality(
566 const char *interface
,
567 const char *property
,
568 sd_bus_message
*reply
,
570 sd_bus_error
*error
) {
572 ExecContext
*c
= userdata
;
578 return sd_bus_message_append(reply
, "s", personality_to_string(c
->personality
));
581 static int property_get_address_families(
584 const char *interface
,
585 const char *property
,
586 sd_bus_message
*reply
,
588 sd_bus_error
*error
) {
590 ExecContext
*c
= userdata
;
591 _cleanup_strv_free_
char **l
= NULL
;
600 r
= sd_bus_message_open_container(reply
, 'r', "bas");
604 r
= sd_bus_message_append(reply
, "b", c
->address_families_whitelist
);
608 SET_FOREACH(af
, c
->address_families
, i
) {
611 name
= af_to_name(PTR_TO_INT(af
));
615 r
= strv_extend(&l
, name
);
622 r
= sd_bus_message_append_strv(reply
, l
);
626 return sd_bus_message_close_container(reply
);
629 static int property_get_working_directory(
632 const char *interface
,
633 const char *property
,
634 sd_bus_message
*reply
,
636 sd_bus_error
*error
) {
638 ExecContext
*c
= userdata
;
645 if (c
->working_directory_home
)
648 wd
= c
->working_directory
;
650 if (c
->working_directory_missing_ok
)
651 wd
= strjoina("!", wd
);
653 return sd_bus_message_append(reply
, "s", wd
);
656 static int property_get_syslog_level(
659 const char *interface
,
660 const char *property
,
661 sd_bus_message
*reply
,
663 sd_bus_error
*error
) {
665 ExecContext
*c
= userdata
;
671 return sd_bus_message_append(reply
, "i", LOG_PRI(c
->syslog_priority
));
674 static int property_get_syslog_facility(
677 const char *interface
,
678 const char *property
,
679 sd_bus_message
*reply
,
681 sd_bus_error
*error
) {
683 ExecContext
*c
= userdata
;
689 return sd_bus_message_append(reply
, "i", LOG_FAC(c
->syslog_priority
));
692 static int property_get_stdio_fdname(
695 const char *interface
,
696 const char *property
,
697 sd_bus_message
*reply
,
699 sd_bus_error
*error
) {
701 ExecContext
*c
= userdata
;
709 if (streq(property
, "StandardInputFileDescriptorName"))
710 fileno
= STDIN_FILENO
;
711 else if (streq(property
, "StandardOutputFileDescriptorName"))
712 fileno
= STDOUT_FILENO
;
714 assert(streq(property
, "StandardErrorFileDescriptorName"));
715 fileno
= STDERR_FILENO
;
718 return sd_bus_message_append(reply
, "s", exec_context_fdname(c
, fileno
));
721 static int property_get_input_data(
724 const char *interface
,
725 const char *property
,
726 sd_bus_message
*reply
,
728 sd_bus_error
*error
) {
730 ExecContext
*c
= userdata
;
737 return sd_bus_message_append_array(reply
, 'y', c
->stdin_data
, c
->stdin_data_size
);
740 static int property_get_bind_paths(
743 const char *interface
,
744 const char *property
,
745 sd_bus_message
*reply
,
747 sd_bus_error
*error
) {
749 ExecContext
*c
= userdata
;
759 ro
= !!strstr(property
, "ReadOnly");
761 r
= sd_bus_message_open_container(reply
, 'a', "(ssbt)");
765 for (i
= 0; i
< c
->n_bind_mounts
; i
++) {
767 if (ro
!= c
->bind_mounts
[i
].read_only
)
770 r
= sd_bus_message_append(
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);
780 return sd_bus_message_close_container(reply
);
783 static int property_get_log_extra_fields(
786 const char *interface
,
787 const char *property
,
788 sd_bus_message
*reply
,
790 sd_bus_error
*error
) {
792 ExecContext
*c
= userdata
;
801 r
= sd_bus_message_open_container(reply
, 'a', "ay");
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
);
811 return sd_bus_message_close_container(reply
);
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
),
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
),
949 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
958 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
962 r
= sd_bus_message_append(reply
, "s", c
->path
);
966 r
= sd_bus_message_append_strv(reply
, c
->argv
);
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
);
982 return sd_bus_message_close_container(reply
);
985 int bus_property_get_exec_command(
988 const char *interface
,
989 const char *property
,
990 sd_bus_message
*reply
,
992 sd_bus_error
*ret_error
) {
994 ExecCommand
*c
= (ExecCommand
*) userdata
;
1000 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
1004 r
= append_exec_command(reply
, c
);
1008 return sd_bus_message_close_container(reply
);
1011 int bus_property_get_exec_command_list(
1014 const char *interface
,
1015 const char *property
,
1016 sd_bus_message
*reply
,
1018 sd_bus_error
*ret_error
) {
1020 ExecCommand
*c
= *(ExecCommand
**) userdata
;
1026 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
1030 LIST_FOREACH(command
, c
, c
) {
1031 r
= append_exec_command(reply
, c
);
1036 return sd_bus_message_close_container(reply
);
1039 int bus_exec_context_set_transient_property(
1043 sd_bus_message
*message
,
1044 UnitWriteFlags flags
,
1045 sd_bus_error
*error
) {
1047 const char *soft
= NULL
;
1055 flags
|= UNIT_PRIVATE
;
1057 if (streq(name
, "User")) {
1060 r
= sd_bus_message_read(message
, "s", &uu
);
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
);
1067 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1069 r
= free_and_strdup(&c
->user
, empty_to_null(uu
));
1073 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "User=%s", uu
);
1078 } else if (streq(name
, "Group")) {
1081 r
= sd_bus_message_read(message
, "s", &gg
);
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
);
1088 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1090 r
= free_and_strdup(&c
->group
, empty_to_null(gg
));
1094 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "Group=%s", gg
);
1099 } else if (streq(name
, "SupplementaryGroups")) {
1100 _cleanup_strv_free_
char **l
= NULL
;
1103 r
= sd_bus_message_read_strv(message
, &l
);
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");
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
);
1117 _cleanup_free_
char *joined
= NULL
;
1119 r
= strv_extend_strv(&c
->supplementary_groups
, l
, true);
1123 joined
= strv_join(c
->supplementary_groups
, " ");
1127 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s", name
, joined
);
1133 } else if (streq(name
, "SyslogIdentifier")) {
1136 r
= sd_bus_message_read(message
, "s", &id
);
1140 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1143 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
1144 else if (free_and_strdup(&c
->syslog_identifier
, id
) < 0)
1147 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "SyslogIdentifier=%s", id
);
1151 } else if (streq(name
, "SyslogLevel")) {
1154 r
= sd_bus_message_read(message
, "i", &level
);
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");
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
);
1167 } else if (streq(name
, "SyslogFacility")) {
1170 r
= sd_bus_message_read(message
, "i", &facility
);
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");
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
);
1184 } else if (streq(name
, "LogLevelMax")) {
1187 r
= sd_bus_message_read(message
, "i", &level
);
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");
1194 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1195 c
->log_level_max
= level
;
1196 unit_write_settingf(u
, flags
, name
, "LogLevelMax=%i", level
);
1201 } else if (streq(name
, "LogExtraFields")) {
1204 r
= sd_bus_message_enter_container(message
, 'a', "ay");
1209 _cleanup_free_
void *copy
= NULL
;
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. */
1222 r
= sd_bus_message_read_array(message
, 'y', &p
, &sz
);
1228 if (memchr(p
, 0, sz
))
1229 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field contains zero byte");
1231 eq
= memchr(p
, '=', sz
);
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");
1237 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1238 t
= realloc_multiply(c
->log_extra_fields
, sizeof(struct iovec
), c
->n_log_extra_fields
+1);
1241 c
->log_extra_fields
= t
;
1244 copy
= malloc(sz
+ 1);
1248 memcpy(copy
, p
, sz
);
1249 ((uint8_t*) copy
)[sz
] = 0;
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");
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
);
1264 r
= sd_bus_message_exit_container(message
);
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=");
1275 } else if (streq(name
, "SecureBits")) {
1278 r
= sd_bus_message_read(message
, "i", &n
);
1282 if (!secure_bits_is_valid(n
))
1283 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid secure bits");
1285 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1286 _cleanup_free_
char *str
= NULL
;
1289 r
= secure_bits_to_string_alloc(n
, &str
);
1293 unit_write_settingf(u
, flags
, name
, "SecureBits=%s", str
);
1297 } else if (STR_IN_SET(name
, "CapabilityBoundingSet", "AmbientCapabilities")) {
1300 r
= sd_bus_message_read(message
, "t", &n
);
1304 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1305 _cleanup_free_
char *str
= NULL
;
1307 if (streq(name
, "CapabilityBoundingSet"))
1308 c
->capability_bounding_set
= n
;
1309 else /* "AmbientCapabilities" */
1310 c
->capability_ambient_set
= n
;
1312 r
= capability_set_to_string_alloc(n
, &str
);
1316 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, str
);
1321 } else if (streq(name
, "Personality")) {
1325 r
= sd_bus_message_read(message
, "s", &s
);
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");
1333 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1335 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, s
);
1342 } else if (streq(name
, "SystemCallFilter")) {
1344 _cleanup_strv_free_
char **l
= NULL
;
1346 r
= sd_bus_message_enter_container(message
, 'r', "bas");
1350 r
= sd_bus_message_read(message
, "b", &whitelist
);
1354 r
= sd_bus_message_read_strv(message
, &l
);
1358 r
= sd_bus_message_exit_container(message
);
1362 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1363 _cleanup_free_
char *joined
= NULL
;
1365 if (strv_isempty(l
)) {
1366 c
->syscall_whitelist
= false;
1367 c
->syscall_filter
= hashmap_free(c
->syscall_filter
);
1371 c
->syscall_whitelist
= whitelist
;
1373 r
= hashmap_ensure_allocated(&c
->syscall_filter
, NULL
);
1377 STRV_FOREACH(s
, l
) {
1378 _cleanup_free_
char *n
= NULL
;
1381 r
= parse_syscall_and_errno(*s
, &n
, &e
);
1386 const SyscallFilterSet
*set
;
1389 set
= syscall_filter_set_find(n
);
1393 NULSTR_FOREACH(i
, set
->value
) {
1396 id
= seccomp_syscall_resolve_name(i
);
1397 if (id
== __NR_SCMP_ERROR
)
1400 r
= hashmap_put(c
->syscall_filter
, INT_TO_PTR(id
+ 1), INT_TO_PTR(e
));
1408 id
= seccomp_syscall_resolve_name(n
);
1409 if (id
== __NR_SCMP_ERROR
)
1412 r
= hashmap_put(c
->syscall_filter
, INT_TO_PTR(id
+ 1), INT_TO_PTR(e
));
1419 joined
= strv_join(l
, " ");
1423 unit_write_settingf(u
, flags
, name
, "SystemCallFilter=%s%s", whitelist
? "" : "~", joined
);
1428 } else if (streq(name
, "SystemCallArchitectures")) {
1429 _cleanup_strv_free_
char **l
= NULL
;
1431 r
= sd_bus_message_read_strv(message
, &l
);
1435 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1436 _cleanup_free_
char *joined
= NULL
;
1438 if (strv_isempty(l
))
1439 c
->syscall_archs
= set_free(c
->syscall_archs
);
1443 r
= set_ensure_allocated(&c
->syscall_archs
, NULL
);
1447 STRV_FOREACH(s
, l
) {
1450 r
= seccomp_arch_from_string(*s
, &a
);
1454 r
= set_put(c
->syscall_archs
, UINT32_TO_PTR(a
+ 1));
1461 joined
= strv_join(l
, " ");
1465 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
1470 } else if (streq(name
, "SystemCallErrorNumber")) {
1473 r
= sd_bus_message_read(message
, "i", &n
);
1477 if (n
<= 0 || n
> ERRNO_MAX
)
1478 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SystemCallErrorNumber");
1480 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1481 c
->syscall_errno
= n
;
1483 unit_write_settingf(u
, flags
, name
, "SystemCallErrorNumber=%d", n
);
1488 } else if (streq(name
, "RestrictAddressFamilies")) {
1490 _cleanup_strv_free_
char **l
= NULL
;
1492 r
= sd_bus_message_enter_container(message
, 'r', "bas");
1496 r
= sd_bus_message_read(message
, "b", &whitelist
);
1500 r
= sd_bus_message_read_strv(message
, &l
);
1504 r
= sd_bus_message_exit_container(message
);
1508 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1509 _cleanup_free_
char *joined
= NULL
;
1511 if (strv_isempty(l
)) {
1512 c
->address_families_whitelist
= false;
1513 c
->address_families
= set_free(c
->address_families
);
1517 c
->address_families_whitelist
= whitelist
;
1519 r
= set_ensure_allocated(&c
->address_families
, NULL
);
1523 STRV_FOREACH(s
, l
) {
1526 af
= af_from_name(*s
);
1530 r
= set_put(c
->address_families
, INT_TO_PTR(af
));
1536 joined
= strv_join(l
, " ");
1540 unit_write_settingf(u
, flags
, name
, "RestrictAddressFamilies=%s%s", whitelist
? "" : "~", joined
);
1546 } else if (streq(name
, "CPUSchedulingPolicy")) {
1549 r
= sd_bus_message_read(message
, "i", &n
);
1553 if (!sched_policy_is_valid(n
))
1554 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid CPU scheduling policy");
1556 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1557 _cleanup_free_
char *str
= NULL
;
1559 c
->cpu_sched_policy
= n
;
1560 r
= sched_policy_to_string_alloc(n
, &str
);
1564 unit_write_settingf(u
, flags
, name
, "CPUSchedulingPolicy=%s", str
);
1569 } else if (streq(name
, "CPUSchedulingPriority")) {
1572 r
= sd_bus_message_read(message
, "i", &n
);
1576 if (!ioprio_priority_is_valid(n
))
1577 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid CPU scheduling priority");
1579 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1580 c
->cpu_sched_priority
= n
;
1581 unit_write_settingf(u
, flags
, name
, "CPUSchedulingPriority=%i", n
);
1586 } else if (streq(name
, "CPUAffinity")) {
1590 r
= sd_bus_message_read_array(message
, 'y', &a
, &n
);
1594 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1596 c
->cpuset
= cpu_set_mfree(c
->cpuset
);
1597 c
->cpuset_ncpus
= 0;
1598 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1600 _cleanup_free_
char *str
= NULL
;
1601 size_t allocated
= 0, len
= 0, i
, ncpus
;
1603 ncpus
= CPU_SIZE_TO_NUM(n
);
1605 for (i
= 0; i
< ncpus
; i
++) {
1606 _cleanup_free_
char *p
= NULL
;
1609 if (!CPU_ISSET_S(i
, n
, (cpu_set_t
*) a
))
1612 r
= asprintf(&p
, "%zu", i
);
1618 if (!GREEDY_REALLOC(str
, allocated
, len
+ add
+ 2))
1621 strcpy(mempcpy(str
+ len
, p
, add
), " ");
1626 str
[len
- 1] = '\0';
1628 if (!c
->cpuset
|| c
->cpuset_ncpus
< ncpus
) {
1631 cpuset
= CPU_ALLOC(ncpus
);
1635 CPU_ZERO_S(n
, cpuset
);
1637 CPU_OR_S(CPU_ALLOC_SIZE(c
->cpuset_ncpus
), cpuset
, c
->cpuset
, (cpu_set_t
*) a
);
1638 CPU_FREE(c
->cpuset
);
1640 CPU_OR_S(n
, cpuset
, cpuset
, (cpu_set_t
*) a
);
1643 c
->cpuset_ncpus
= ncpus
;
1645 CPU_OR_S(n
, c
->cpuset
, c
->cpuset
, (cpu_set_t
*) a
);
1647 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, str
);
1652 } else if (streq(name
, "Nice")) {
1655 r
= sd_bus_message_read(message
, "i", &n
);
1659 if (!nice_is_valid(n
))
1660 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Nice value out of range");
1662 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1664 unit_write_settingf(u
, flags
, name
, "Nice=%i", n
);
1669 } else if (streq(name
, "IOSchedulingClass")) {
1672 r
= sd_bus_message_read(message
, "i", &q
);
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
);
1679 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1680 _cleanup_free_
char *s
= NULL
;
1682 r
= ioprio_class_to_string_alloc(q
, &s
);
1686 c
->ioprio
= IOPRIO_PRIO_VALUE(q
, IOPRIO_PRIO_DATA(c
->ioprio
));
1687 c
->ioprio_set
= true;
1689 unit_write_settingf(u
, flags
, name
, "IOSchedulingClass=%s", s
);
1694 } else if (streq(name
, "IOSchedulingPriority")) {
1697 r
= sd_bus_message_read(message
, "i", &p
);
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
);
1704 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1705 c
->ioprio
= IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c
->ioprio
), p
);
1706 c
->ioprio_set
= true;
1708 unit_write_settingf(u
, flags
, name
, "IOSchedulingPriority=%i", p
);
1713 } else if (STR_IN_SET(name
, "TTYPath", "RootDirectory", "RootImage")) {
1716 r
= sd_bus_message_read(message
, "s", &s
);
1720 if (!path_is_absolute(s
))
1721 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s takes an absolute path", name
);
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
);
1729 assert(streq(name
, "RootDirectory"));
1730 r
= free_and_strdup(&c
->root_directory
, s
);
1735 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s", name
, s
);
1740 } else if (streq(name
, "WorkingDirectory")) {
1744 r
= sd_bus_message_read(message
, "s", &s
);
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 '~'");
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;
1762 r
= free_and_strdup(&c
->working_directory
, s
);
1766 c
->working_directory_home
= false;
1769 c
->working_directory_missing_ok
= missing_ok
;
1770 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
1775 } else if (streq(name
, "StandardInput")) {
1779 r
= sd_bus_message_read(message
, "s", &s
);
1783 p
= exec_input_from_string(s
);
1785 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard input name");
1787 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1790 unit_write_settingf(u
, flags
, name
, "StandardInput=%s", exec_input_to_string(p
));
1795 } else if (streq(name
, "StandardOutput")) {
1799 r
= sd_bus_message_read(message
, "s", &s
);
1803 p
= exec_output_from_string(s
);
1805 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard output name");
1807 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1810 unit_write_settingf(u
, flags
, name
, "StandardOutput=%s", exec_output_to_string(p
));
1815 } else if (streq(name
, "StandardError")) {
1819 r
= sd_bus_message_read(message
, "s", &s
);
1823 p
= exec_output_from_string(s
);
1825 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard error name");
1827 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1830 unit_write_settingf(u
, flags
, name
, "StandardError=%s", exec_output_to_string(p
));
1835 } else if (STR_IN_SET(name
,
1836 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
1839 r
= sd_bus_message_read(message
, "s", &s
);
1845 else if (!fdname_is_valid(s
))
1846 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid file descriptor name");
1848 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1850 if (streq(name
, "StandardInputFileDescriptorName")) {
1851 r
= free_and_strdup(c
->stdio_fdname
+ STDIN_FILENO
, s
);
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
));
1858 } else if (streq(name
, "StandardOutputFileDescriptorName")) {
1859 r
= free_and_strdup(c
->stdio_fdname
+ STDOUT_FILENO
, s
);
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
));
1867 assert(streq(name
, "StandardErrorFileDescriptorName"));
1869 r
= free_and_strdup(&c
->stdio_fdname
[STDERR_FILENO
], s
);
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
));
1880 } else if (STR_IN_SET(name
, "StandardInputFile", "StandardOutputFile", "StandardErrorFile")) {
1883 r
= sd_bus_message_read(message
, "s", &s
);
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
);
1892 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1894 if (streq(name
, "StandardInputFile")) {
1895 r
= free_and_strdup(&c
->stdio_file
[STDIN_FILENO
], s
);
1899 c
->std_input
= EXEC_INPUT_FILE
;
1900 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardInput=file:%s", s
);
1902 } else if (streq(name
, "StandardOutputFile")) {
1903 r
= free_and_strdup(&c
->stdio_file
[STDOUT_FILENO
], s
);
1907 c
->std_output
= EXEC_OUTPUT_FILE
;
1908 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardOutput=file:%s", s
);
1911 assert(streq(name
, "StandardErrorFile"));
1913 r
= free_and_strdup(&c
->stdio_file
[STDERR_FILENO
], s
);
1917 c
->std_error
= EXEC_OUTPUT_FILE
;
1918 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardError=file:%s", s
);
1924 } else if (streq(name
, "StandardInputData")) {
1928 r
= sd_bus_message_read_array(message
, 'y', &p
, &sz
);
1932 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1933 _cleanup_free_
char *encoded
= NULL
;
1936 c
->stdin_data
= mfree(c
->stdin_data
);
1937 c
->stdin_data_size
= 0;
1939 unit_write_settingf(u
, flags
, name
, "StandardInputData=");
1944 if (c
->stdin_data_size
+ sz
< c
->stdin_data_size
|| /* check for overflow */
1945 c
->stdin_data_size
+ sz
> EXEC_STDIN_DATA_MAX
)
1948 n
= base64mem(p
, sz
, &encoded
);
1952 q
= realloc(c
->stdin_data
, c
->stdin_data_size
+ sz
);
1956 memcpy((uint8_t*) q
+ c
->stdin_data_size
, p
, sz
);
1959 c
->stdin_data_size
+= sz
;
1961 unit_write_settingf(u
, flags
, name
, "StandardInputData=%s", encoded
);
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")) {
1976 r
= sd_bus_message_read(message
, "b", &b
);
1980 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1981 if (streq(name
, "IgnoreSIGPIPE"))
1982 c
->ignore_sigpipe
= b
;
1983 else if (streq(name
, "TTYVHangup"))
1985 else if (streq(name
, "TTYReset"))
1987 else if (streq(name
, "TTYVTDisallocate"))
1988 c
->tty_vt_disallocate
= b
;
1989 else if (streq(name
, "PrivateTmp"))
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"))
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
;
2024 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
2029 } else if (streq(name
, "UtmpIdentifier")) {
2032 r
= sd_bus_message_read(message
, "s", &id
);
2036 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2038 r
= free_and_strdup(&c
->utmp_id
, empty_to_null(id
));
2042 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "UtmpIdentifier=%s", strempty(id
));
2047 } else if (streq(name
, "UtmpMode")) {
2051 r
= sd_bus_message_read(message
, "s", &s
);
2055 m
= exec_utmp_mode_from_string(s
);
2057 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid utmp mode");
2059 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2062 unit_write_settingf(u
, flags
, name
, "UtmpMode=%s", exec_utmp_mode_to_string(m
));
2067 } else if (streq(name
, "PAMName")) {
2070 r
= sd_bus_message_read(message
, "s", &n
);
2074 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2076 r
= free_and_strdup(&c
->pam_name
, empty_to_null(n
));
2080 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "PAMName=%s", strempty(n
));
2085 } else if (streq(name
, "Environment")) {
2087 _cleanup_strv_free_
char **l
= NULL
;
2089 r
= sd_bus_message_read_strv(message
, &l
);
2093 if (!strv_env_is_valid(l
))
2094 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
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=");
2101 _cleanup_free_
char *joined
= NULL
;
2104 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
);
2108 e
= strv_env_merge(2, c
->environment
, l
);
2112 strv_free(c
->environment
);
2115 unit_write_settingf(u
, flags
, name
, "Environment=%s", joined
);
2121 } else if (streq(name
, "UnsetEnvironment")) {
2123 _cleanup_strv_free_
char **l
= NULL
;
2125 r
= sd_bus_message_read_strv(message
, &l
);
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.");
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=");
2137 _cleanup_free_
char *joined
= NULL
;
2140 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
);
2144 e
= strv_env_merge(2, c
->unset_environment
, l
);
2148 strv_free(c
->unset_environment
);
2149 c
->unset_environment
= e
;
2151 unit_write_settingf(u
, flags
, name
, "UnsetEnvironment=%s", joined
);
2157 } else if (streq(name
, "TimerSlackNSec")) {
2161 r
= sd_bus_message_read(message
, "t", &n
);
2165 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2166 c
->timer_slack_nsec
= n
;
2167 unit_write_settingf(u
, flags
, name
, "TimerSlackNSec=" NSEC_FMT
, n
);
2172 } else if (streq(name
, "OOMScoreAdjust")) {
2175 r
= sd_bus_message_read(message
, "i", &oa
);
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");
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
);
2190 } else if (streq(name
, "EnvironmentFiles")) {
2192 _cleanup_free_
char *joined
= NULL
;
2193 _cleanup_fclose_
FILE *f
= NULL
;
2194 _cleanup_strv_free_
char **l
= NULL
;
2198 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
2202 f
= open_memstream(&joined
, &size
);
2206 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
2208 fputs("EnvironmentFile=\n", f
);
2210 STRV_FOREACH(i
, c
->environment_files
) {
2211 _cleanup_free_
char *q
= NULL
;
2213 q
= specifier_escape(*i
);
2217 fprintf(f
, "EnvironmentFile=%s\n", q
);
2220 while ((r
= sd_bus_message_enter_container(message
, 'r', "sb")) > 0) {
2224 r
= sd_bus_message_read(message
, "sb", &path
, &b
);
2228 r
= sd_bus_message_exit_container(message
);
2232 if (!path_is_absolute(path
))
2233 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not absolute.", path
);
2235 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2236 _cleanup_free_
char *q
= NULL
;
2239 buf
= strjoin(b
? "-" : "", path
);
2243 q
= specifier_escape(buf
);
2249 fprintf(f
, "EnvironmentFile=%s\n", q
);
2251 r
= strv_consume(&l
, buf
);
2259 r
= sd_bus_message_exit_container(message
);
2263 r
= fflush_and_check(f
);
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=");
2272 r
= strv_extend_strv(&c
->environment_files
, l
, true);
2276 unit_write_setting(u
, flags
, name
, joined
);
2282 } else if (streq(name
, "PassEnvironment")) {
2284 _cleanup_strv_free_
char **l
= NULL
;
2286 r
= sd_bus_message_read_strv(message
, &l
);
2290 if (!strv_env_name_is_valid(l
))
2291 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid PassEnvironment= block.");
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=");
2298 _cleanup_free_
char *joined
= NULL
;
2300 r
= strv_extend_strv(&c
->pass_environment
, l
, true);
2304 /* We write just the new settings out to file, with unresolved specifiers. */
2305 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
2309 unit_write_settingf(u
, flags
, name
, "PassEnvironment=%s", joined
);
2315 } else if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
2316 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) {
2317 _cleanup_strv_free_
char **l
= NULL
;
2321 r
= sd_bus_message_read_strv(message
, &l
);
2325 STRV_FOREACH(p
, l
) {
2329 if (!utf8_is_valid(i
))
2330 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
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
);
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
;
2346 if (strv_isempty(l
)) {
2347 *dirs
= strv_free(*dirs
);
2348 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2350 _cleanup_free_
char *joined
= NULL
;
2352 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
2356 r
= strv_extend_strv(dirs
, l
, true);
2360 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
2366 } else if (streq(name
, "ProtectSystem")) {
2370 r
= sd_bus_message_read(message
, "s", &s
);
2374 r
= parse_boolean(s
);
2376 ps
= PROTECT_SYSTEM_YES
;
2378 ps
= PROTECT_SYSTEM_NO
;
2380 ps
= protect_system_from_string(s
);
2382 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect system value");
2385 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2386 c
->protect_system
= ps
;
2387 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, s
);
2392 } else if (streq(name
, "ProtectHome")) {
2396 r
= sd_bus_message_read(message
, "s", &s
);
2400 r
= parse_boolean(s
);
2402 ph
= PROTECT_HOME_YES
;
2404 ph
= PROTECT_HOME_NO
;
2406 ph
= protect_home_from_string(s
);
2408 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect home value");
2411 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2412 c
->protect_home
= ph
;
2413 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, s
);
2418 } else if (streq(name
, "KeyringMode")) {
2423 r
= sd_bus_message_read(message
, "s", &s
);
2427 m
= exec_keyring_mode_from_string(s
);
2429 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid keyring mode");
2431 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2432 c
->keyring_mode
= m
;
2434 unit_write_settingf(u
, flags
, name
, "KeyringMode=%s", exec_keyring_mode_to_string(m
));
2439 } else if (streq(name
, "RuntimeDirectoryPreserve")) {
2443 r
= sd_bus_message_read(message
, "s", &s
);
2447 m
= exec_preserve_mode_from_string(s
);
2449 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid preserve mode");
2451 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2452 c
->runtime_directory_preserve_mode
= m
;
2454 unit_write_settingf(u
, flags
, name
, "RuntimeDirectoryPreserve=%s", exec_preserve_mode_to_string(m
));
2459 } else if (STR_IN_SET(name
, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode", "UMask")) {
2462 r
= sd_bus_message_read(message
, "u", &m
);
2466 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2467 ExecDirectoryType i
;
2469 if (streq(name
, "UMask"))
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
;
2478 unit_write_settingf(u
, flags
, name
, "%s=%040o", name
, m
);
2483 } else if (STR_IN_SET(name
, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
2484 _cleanup_strv_free_
char **l
= NULL
;
2487 r
= sd_bus_message_read_strv(message
, &l
);
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
);
2496 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2497 char ***dirs
= NULL
;
2498 ExecDirectoryType i
;
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
;
2508 if (strv_isempty(l
)) {
2509 *dirs
= strv_free(*dirs
);
2510 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2512 _cleanup_free_
char *joined
= NULL
;
2514 r
= strv_extend_strv(dirs
, l
, true);
2518 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
2522 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
2528 } else if (streq(name
, "SELinuxContext")) {
2530 r
= sd_bus_message_read(message
, "s", &s
);
2534 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2536 c
->selinux_context
= mfree(c
->selinux_context
);
2537 else if (free_and_strdup(&c
->selinux_context
, s
) < 0)
2540 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s", name
, strempty(s
));
2545 } else if (STR_IN_SET(name
, "AppArmorProfile", "SmackProcessLabel")) {
2549 r
= sd_bus_message_enter_container(message
, 'r', "bs");
2553 r
= sd_bus_message_read(message
, "bs", &ignore
, &s
);
2557 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
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
;
2573 if (free_and_strdup(p
, s
) < 0)
2578 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s%s", name
, ignore
? "-" : "", strempty(s
));
2583 } else if (streq(name
, "RestrictNamespaces")) {
2586 r
= sd_bus_message_read(message
, "t", &rf
);
2589 if ((rf
& NAMESPACE_FLAGS_ALL
) != rf
)
2590 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown namespace types");
2592 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2593 _cleanup_free_
char *s
= NULL
;
2595 r
= namespace_flag_to_string_many(rf
, &s
);
2599 c
->restrict_namespaces
= rf
;
2600 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, s
);
2604 } else if (streq(name
, "MountFlags")) {
2607 r
= sd_bus_message_read(message
, "t", &fl
);
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");
2613 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2614 c
->mount_flags
= fl
;
2616 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, mount_propagation_flags_to_string(fl
));
2620 } else if (STR_IN_SET(name
, "BindPaths", "BindReadOnlyPaths")) {
2621 unsigned empty
= true;
2623 r
= sd_bus_message_enter_container(message
, 'a', "(ssbt)");
2627 while ((r
= sd_bus_message_enter_container(message
, 'r', "ssbt")) > 0) {
2628 const char *source
, *destination
;
2630 uint64_t mount_flags
;
2632 r
= sd_bus_message_read(message
, "ssbt", &source
, &destination
, &ignore_enoent
, &mount_flags
);
2636 r
= sd_bus_message_exit_container(message
);
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.");
2647 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2648 r
= bind_mount_add(&c
->bind_mounts
, &c
->n_bind_mounts
,
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
,
2659 unit_write_settingf(
2660 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
,
2663 ignore_enoent
? "-" : "",
2666 (mount_flags
& MS_REC
) ? "rbind" : "norbind");
2674 r
= sd_bus_message_exit_container(message
);
2679 bind_mount_free_many(c
->bind_mounts
, c
->n_bind_mounts
);
2680 c
->bind_mounts
= NULL
;
2681 c
->n_bind_mounts
= 0;
2683 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2689 ri
= rlimit_from_string(name
);
2691 soft
= endswith(name
, "Soft");
2695 n
= strndupa(name
, soft
- name
);
2696 ri
= rlimit_from_string(n
);
2707 r
= sd_bus_message_read(message
, "t", &rl
);
2711 if (rl
== (uint64_t) -1)
2716 if ((uint64_t) x
!= rl
)
2720 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2721 _cleanup_free_
char *f
= NULL
;
2724 if (c
->rlimit
[ri
]) {
2725 nl
= *c
->rlimit
[ri
];
2732 /* When the resource limit is not initialized yet, then assign the value to both fields */
2733 nl
= (struct rlimit
) {
2738 r
= rlimit_format(&nl
, &f
);
2743 *c
->rlimit
[ri
] = nl
;
2745 c
->rlimit
[ri
] = newdup(struct rlimit
, &nl
, 1);
2750 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, f
);