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>
28 #include "alloc-util.h"
31 #include "capability-util.h"
32 #include "cpu-set-util.h"
33 #include "dbus-execute.h"
35 #include "errno-list.h"
40 #include "hexdecoct.h"
43 #include "journal-util.h"
45 #include "mount-util.h"
46 #include "namespace.h"
47 #include "parse-util.h"
48 #include "path-util.h"
49 #include "process-util.h"
50 #include "rlimit-util.h"
52 #include "seccomp-util.h"
54 #include "securebits-util.h"
55 #include "specifier.h"
57 #include "syslog-util.h"
58 #include "unit-printf.h"
59 #include "user-util.h"
62 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output
, exec_output
, ExecOutput
);
63 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input
, exec_input
, ExecInput
);
65 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode
, exec_utmp_mode
, ExecUtmpMode
);
66 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode
, exec_preserve_mode
, ExecPreserveMode
);
67 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode
, exec_keyring_mode
, ExecKeyringMode
);
69 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home
, protect_home
, ProtectHome
);
70 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system
, protect_system
, ProtectSystem
);
72 static int property_get_environment_files(
75 const char *interface
,
77 sd_bus_message
*reply
,
79 sd_bus_error
*error
) {
81 ExecContext
*c
= userdata
;
89 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
93 STRV_FOREACH(j
, c
->environment_files
) {
96 r
= sd_bus_message_append(reply
, "(sb)", fn
[0] == '-' ? fn
+ 1 : fn
, fn
[0] == '-');
101 return sd_bus_message_close_container(reply
);
104 static int property_get_oom_score_adjust(
107 const char *interface
,
108 const char *property
,
109 sd_bus_message
*reply
,
111 sd_bus_error
*error
) {
114 ExecContext
*c
= userdata
;
121 if (c
->oom_score_adjust_set
)
122 n
= c
->oom_score_adjust
;
124 _cleanup_free_
char *t
= NULL
;
127 if (read_one_line_file("/proc/self/oom_score_adj", &t
) >= 0)
131 return sd_bus_message_append(reply
, "i", n
);
134 static int property_get_nice(
137 const char *interface
,
138 const char *property
,
139 sd_bus_message
*reply
,
141 sd_bus_error
*error
) {
144 ExecContext
*c
= userdata
;
155 n
= getpriority(PRIO_PROCESS
, 0);
160 return sd_bus_message_append(reply
, "i", n
);
163 static int property_get_ioprio(
166 const char *interface
,
167 const char *property
,
168 sd_bus_message
*reply
,
170 sd_bus_error
*error
) {
173 ExecContext
*c
= userdata
;
179 return sd_bus_message_append(reply
, "i", exec_context_get_effective_ioprio(c
));
182 static int property_get_ioprio_class(
185 const char *interface
,
186 const char *property
,
187 sd_bus_message
*reply
,
189 sd_bus_error
*error
) {
192 ExecContext
*c
= userdata
;
198 return sd_bus_message_append(reply
, "i", IOPRIO_PRIO_CLASS(exec_context_get_effective_ioprio(c
)));
201 static int property_get_ioprio_priority(
204 const char *interface
,
205 const char *property
,
206 sd_bus_message
*reply
,
208 sd_bus_error
*error
) {
211 ExecContext
*c
= userdata
;
217 return sd_bus_message_append(reply
, "i", IOPRIO_PRIO_DATA(exec_context_get_effective_ioprio(c
)));
220 static int property_get_cpu_sched_policy(
223 const char *interface
,
224 const char *property
,
225 sd_bus_message
*reply
,
227 sd_bus_error
*error
) {
229 ExecContext
*c
= userdata
;
236 if (c
->cpu_sched_set
)
237 n
= c
->cpu_sched_policy
;
239 n
= sched_getscheduler(0);
244 return sd_bus_message_append(reply
, "i", n
);
247 static int property_get_cpu_sched_priority(
250 const char *interface
,
251 const char *property
,
252 sd_bus_message
*reply
,
254 sd_bus_error
*error
) {
256 ExecContext
*c
= userdata
;
263 if (c
->cpu_sched_set
)
264 n
= c
->cpu_sched_priority
;
266 struct sched_param p
= {};
268 if (sched_getparam(0, &p
) >= 0)
269 n
= p
.sched_priority
;
274 return sd_bus_message_append(reply
, "i", n
);
277 static int property_get_cpu_affinity(
280 const char *interface
,
281 const char *property
,
282 sd_bus_message
*reply
,
284 sd_bus_error
*error
) {
286 ExecContext
*c
= userdata
;
293 return sd_bus_message_append_array(reply
, 'y', c
->cpuset
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
));
295 return sd_bus_message_append_array(reply
, 'y', NULL
, 0);
298 static int property_get_timer_slack_nsec(
301 const char *interface
,
302 const char *property
,
303 sd_bus_message
*reply
,
305 sd_bus_error
*error
) {
307 ExecContext
*c
= userdata
;
314 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
315 u
= (uint64_t) c
->timer_slack_nsec
;
317 u
= (uint64_t) prctl(PR_GET_TIMERSLACK
);
319 return sd_bus_message_append(reply
, "t", u
);
322 static int property_get_capability_bounding_set(
325 const char *interface
,
326 const char *property
,
327 sd_bus_message
*reply
,
329 sd_bus_error
*error
) {
331 ExecContext
*c
= userdata
;
337 return sd_bus_message_append(reply
, "t", c
->capability_bounding_set
);
340 static int property_get_ambient_capabilities(
343 const char *interface
,
344 const char *property
,
345 sd_bus_message
*reply
,
347 sd_bus_error
*error
) {
349 ExecContext
*c
= userdata
;
355 return sd_bus_message_append(reply
, "t", c
->capability_ambient_set
);
358 static int property_get_empty_string(
361 const char *interface
,
362 const char *property
,
363 sd_bus_message
*reply
,
365 sd_bus_error
*error
) {
370 return sd_bus_message_append(reply
, "s", "");
373 static int property_get_syscall_filter(
376 const char *interface
,
377 const char *property
,
378 sd_bus_message
*reply
,
380 sd_bus_error
*error
) {
382 ExecContext
*c
= userdata
;
383 _cleanup_strv_free_
char **l
= NULL
;
395 r
= sd_bus_message_open_container(reply
, 'r', "bas");
399 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
404 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_filter
, i
) {
405 _cleanup_free_
char *name
= NULL
;
406 const char *e
= NULL
;
408 int num
= PTR_TO_INT(val
);
410 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
415 e
= errno_to_name(num
);
417 s
= strjoin(name
, ":", e
);
421 r
= asprintf(&s
, "%s:%d", name
, num
);
430 r
= strv_consume(&l
, s
);
438 r
= sd_bus_message_append_strv(reply
, l
);
442 return sd_bus_message_close_container(reply
);
445 static int property_get_syscall_archs(
448 const char *interface
,
449 const char *property
,
450 sd_bus_message
*reply
,
452 sd_bus_error
*error
) {
454 ExecContext
*c
= userdata
;
455 _cleanup_strv_free_
char **l
= NULL
;
468 SET_FOREACH(id
, c
->syscall_archs
, i
) {
471 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
475 r
= strv_extend(&l
, name
);
483 r
= sd_bus_message_append_strv(reply
, l
);
490 static int property_get_syscall_errno(
493 const char *interface
,
494 const char *property
,
495 sd_bus_message
*reply
,
497 sd_bus_error
*error
) {
499 ExecContext
*c
= userdata
;
505 return sd_bus_message_append(reply
, "i", (int32_t) c
->syscall_errno
);
508 static int property_get_selinux_context(
511 const char *interface
,
512 const char *property
,
513 sd_bus_message
*reply
,
515 sd_bus_error
*error
) {
517 ExecContext
*c
= userdata
;
523 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
526 static int property_get_apparmor_profile(
529 const char *interface
,
530 const char *property
,
531 sd_bus_message
*reply
,
533 sd_bus_error
*error
) {
535 ExecContext
*c
= userdata
;
541 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
544 static int property_get_smack_process_label(
547 const char *interface
,
548 const char *property
,
549 sd_bus_message
*reply
,
551 sd_bus_error
*error
) {
553 ExecContext
*c
= userdata
;
559 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
562 static int property_get_personality(
565 const char *interface
,
566 const char *property
,
567 sd_bus_message
*reply
,
569 sd_bus_error
*error
) {
571 ExecContext
*c
= userdata
;
577 return sd_bus_message_append(reply
, "s", personality_to_string(c
->personality
));
580 static int property_get_address_families(
583 const char *interface
,
584 const char *property
,
585 sd_bus_message
*reply
,
587 sd_bus_error
*error
) {
589 ExecContext
*c
= userdata
;
590 _cleanup_strv_free_
char **l
= NULL
;
599 r
= sd_bus_message_open_container(reply
, 'r', "bas");
603 r
= sd_bus_message_append(reply
, "b", c
->address_families_whitelist
);
607 SET_FOREACH(af
, c
->address_families
, i
) {
610 name
= af_to_name(PTR_TO_INT(af
));
614 r
= strv_extend(&l
, name
);
621 r
= sd_bus_message_append_strv(reply
, l
);
625 return sd_bus_message_close_container(reply
);
628 static int property_get_working_directory(
631 const char *interface
,
632 const char *property
,
633 sd_bus_message
*reply
,
635 sd_bus_error
*error
) {
637 ExecContext
*c
= userdata
;
644 if (c
->working_directory_home
)
647 wd
= c
->working_directory
;
649 if (c
->working_directory_missing_ok
)
650 wd
= strjoina("!", wd
);
652 return sd_bus_message_append(reply
, "s", wd
);
655 static int property_get_syslog_level(
658 const char *interface
,
659 const char *property
,
660 sd_bus_message
*reply
,
662 sd_bus_error
*error
) {
664 ExecContext
*c
= userdata
;
670 return sd_bus_message_append(reply
, "i", LOG_PRI(c
->syslog_priority
));
673 static int property_get_syslog_facility(
676 const char *interface
,
677 const char *property
,
678 sd_bus_message
*reply
,
680 sd_bus_error
*error
) {
682 ExecContext
*c
= userdata
;
688 return sd_bus_message_append(reply
, "i", LOG_FAC(c
->syslog_priority
));
691 static int property_get_stdio_fdname(
694 const char *interface
,
695 const char *property
,
696 sd_bus_message
*reply
,
698 sd_bus_error
*error
) {
700 ExecContext
*c
= userdata
;
708 if (streq(property
, "StandardInputFileDescriptorName"))
709 fileno
= STDIN_FILENO
;
710 else if (streq(property
, "StandardOutputFileDescriptorName"))
711 fileno
= STDOUT_FILENO
;
713 assert(streq(property
, "StandardErrorFileDescriptorName"));
714 fileno
= STDERR_FILENO
;
717 return sd_bus_message_append(reply
, "s", exec_context_fdname(c
, fileno
));
720 static int property_get_input_data(
723 const char *interface
,
724 const char *property
,
725 sd_bus_message
*reply
,
727 sd_bus_error
*error
) {
729 ExecContext
*c
= userdata
;
736 return sd_bus_message_append_array(reply
, 'y', c
->stdin_data
, c
->stdin_data_size
);
739 static int property_get_bind_paths(
742 const char *interface
,
743 const char *property
,
744 sd_bus_message
*reply
,
746 sd_bus_error
*error
) {
748 ExecContext
*c
= userdata
;
758 ro
= !!strstr(property
, "ReadOnly");
760 r
= sd_bus_message_open_container(reply
, 'a', "(ssbt)");
764 for (i
= 0; i
< c
->n_bind_mounts
; i
++) {
766 if (ro
!= c
->bind_mounts
[i
].read_only
)
769 r
= sd_bus_message_append(
771 c
->bind_mounts
[i
].source
,
772 c
->bind_mounts
[i
].destination
,
773 c
->bind_mounts
[i
].ignore_enoent
,
774 c
->bind_mounts
[i
].recursive
? (uint64_t) MS_REC
: (uint64_t) 0);
779 return sd_bus_message_close_container(reply
);
782 static int property_get_log_extra_fields(
785 const char *interface
,
786 const char *property
,
787 sd_bus_message
*reply
,
789 sd_bus_error
*error
) {
791 ExecContext
*c
= userdata
;
800 r
= sd_bus_message_open_container(reply
, 'a', "ay");
804 for (i
= 0; i
< c
->n_log_extra_fields
; i
++) {
805 r
= sd_bus_message_append_array(reply
, 'y', c
->log_extra_fields
[i
].iov_base
, c
->log_extra_fields
[i
].iov_len
);
810 return sd_bus_message_close_container(reply
);
813 const sd_bus_vtable bus_exec_vtable
[] = {
814 SD_BUS_VTABLE_START(0),
815 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
816 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
817 SD_BUS_PROPERTY("PassEnvironment", "as", NULL
, offsetof(ExecContext
, pass_environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
818 SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL
, offsetof(ExecContext
, unset_environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
819 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
820 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
821 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
822 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
823 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
824 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
825 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
826 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
827 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
828 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
829 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
830 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
831 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
832 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
833 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
834 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
835 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
836 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
837 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
838 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
839 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
840 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
841 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
842 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
843 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
844 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
845 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
846 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
847 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
848 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
849 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
850 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
851 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
852 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
853 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
854 SD_BUS_PROPERTY("RootImage", "s", NULL
, offsetof(ExecContext
, root_image
), SD_BUS_VTABLE_PROPERTY_CONST
),
855 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
856 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
857 SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
858 SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
859 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
860 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
861 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
862 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
863 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
864 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
865 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
866 SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_stdio_fdname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
867 SD_BUS_PROPERTY("StandardInputData", "ay", property_get_input_data
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
868 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
869 SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_stdio_fdname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
870 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
871 SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_stdio_fdname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
872 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
873 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
874 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
875 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
876 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
877 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
878 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
879 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
880 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
881 SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int
, offsetof(ExecContext
, log_level_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
882 SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
883 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
884 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
885 SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
886 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
887 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
888 SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool
, offsetof(ExecContext
, dynamic_user
), SD_BUS_VTABLE_PROPERTY_CONST
),
889 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool
, offsetof(ExecContext
, remove_ipc
), SD_BUS_VTABLE_PROPERTY_CONST
),
890 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
891 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
892 SD_BUS_PROPERTY("ReadWritePaths", "as", NULL
, offsetof(ExecContext
, read_write_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
893 SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL
, offsetof(ExecContext
, read_only_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
894 SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL
, offsetof(ExecContext
, inaccessible_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
895 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_flags
), SD_BUS_VTABLE_PROPERTY_CONST
),
896 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
897 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
898 SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_kernel_tunables
), SD_BUS_VTABLE_PROPERTY_CONST
),
899 SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_kernel_modules
), SD_BUS_VTABLE_PROPERTY_CONST
),
900 SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_control_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
901 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
902 SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool
, offsetof(ExecContext
, private_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
903 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
904 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
905 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
906 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
907 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
908 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
909 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
910 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
911 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
912 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
913 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
914 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
915 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
916 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
917 SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool
, offsetof(ExecContext
, lock_personality
), SD_BUS_VTABLE_PROPERTY_CONST
),
918 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
919 SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode
, offsetof(ExecContext
, runtime_directory_preserve_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
920 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_RUNTIME
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
921 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_RUNTIME
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
922 SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_STATE
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
923 SD_BUS_PROPERTY("StateDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_STATE
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
924 SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CACHE
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
925 SD_BUS_PROPERTY("CacheDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CACHE
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
926 SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_LOGS
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
927 SD_BUS_PROPERTY("LogsDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_LOGS
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
928 SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CONFIGURATION
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
929 SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CONFIGURATION
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
930 SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool
, offsetof(ExecContext
, memory_deny_write_execute
), SD_BUS_VTABLE_PROPERTY_CONST
),
931 SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool
, offsetof(ExecContext
, restrict_realtime
), SD_BUS_VTABLE_PROPERTY_CONST
),
932 SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong
, offsetof(ExecContext
, restrict_namespaces
), SD_BUS_VTABLE_PROPERTY_CONST
),
933 SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
934 SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
935 SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool
, offsetof(ExecContext
, mount_apivfs
), SD_BUS_VTABLE_PROPERTY_CONST
),
936 SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode
, offsetof(ExecContext
, keyring_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
938 /* Obsolete/redundant properties: */
939 SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string
, 0, SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
940 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_paths
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
941 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_paths
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
942 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_paths
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
943 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
948 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
957 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
961 r
= sd_bus_message_append(reply
, "s", c
->path
);
965 r
= sd_bus_message_append_strv(reply
, c
->argv
);
969 r
= sd_bus_message_append(reply
, "bttttuii",
970 !!(c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
),
971 c
->exec_status
.start_timestamp
.realtime
,
972 c
->exec_status
.start_timestamp
.monotonic
,
973 c
->exec_status
.exit_timestamp
.realtime
,
974 c
->exec_status
.exit_timestamp
.monotonic
,
975 (uint32_t) c
->exec_status
.pid
,
976 (int32_t) c
->exec_status
.code
,
977 (int32_t) c
->exec_status
.status
);
981 return sd_bus_message_close_container(reply
);
984 int bus_property_get_exec_command(
987 const char *interface
,
988 const char *property
,
989 sd_bus_message
*reply
,
991 sd_bus_error
*ret_error
) {
993 ExecCommand
*c
= (ExecCommand
*) userdata
;
999 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
1003 r
= append_exec_command(reply
, c
);
1007 return sd_bus_message_close_container(reply
);
1010 int bus_property_get_exec_command_list(
1013 const char *interface
,
1014 const char *property
,
1015 sd_bus_message
*reply
,
1017 sd_bus_error
*ret_error
) {
1019 ExecCommand
*c
= *(ExecCommand
**) userdata
;
1025 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
1029 LIST_FOREACH(command
, c
, c
) {
1030 r
= append_exec_command(reply
, c
);
1035 return sd_bus_message_close_container(reply
);
1038 int bus_exec_context_set_transient_property(
1042 sd_bus_message
*message
,
1043 UnitWriteFlags flags
,
1044 sd_bus_error
*error
) {
1046 const char *soft
= NULL
;
1054 flags
|= UNIT_PRIVATE
;
1056 if (streq(name
, "User")) {
1059 r
= sd_bus_message_read(message
, "s", &uu
);
1063 if (!isempty(uu
) && !valid_user_group_name_or_id(uu
))
1064 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user name: %s", uu
);
1066 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1068 r
= free_and_strdup(&c
->user
, empty_to_null(uu
));
1072 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "User=%s", uu
);
1077 } else if (streq(name
, "Group")) {
1080 r
= sd_bus_message_read(message
, "s", &gg
);
1084 if (!isempty(gg
) && !valid_user_group_name_or_id(gg
))
1085 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group name: %s", gg
);
1087 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1089 r
= free_and_strdup(&c
->group
, empty_to_null(gg
));
1093 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "Group=%s", gg
);
1098 } else if (streq(name
, "SupplementaryGroups")) {
1099 _cleanup_strv_free_
char **l
= NULL
;
1102 r
= sd_bus_message_read_strv(message
, &l
);
1106 STRV_FOREACH(p
, l
) {
1107 if (!isempty(*p
) && !valid_user_group_name_or_id(*p
))
1108 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid supplementary group names");
1111 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1112 if (strv_isempty(l
)) {
1113 c
->supplementary_groups
= strv_free(c
->supplementary_groups
);
1114 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1116 _cleanup_free_
char *joined
= NULL
;
1118 r
= strv_extend_strv(&c
->supplementary_groups
, l
, true);
1122 joined
= strv_join(c
->supplementary_groups
, " ");
1126 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s", name
, joined
);
1132 } else if (streq(name
, "SyslogIdentifier")) {
1135 r
= sd_bus_message_read(message
, "s", &id
);
1139 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1142 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
1143 else if (free_and_strdup(&c
->syslog_identifier
, id
) < 0)
1146 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "SyslogIdentifier=%s", id
);
1150 } else if (streq(name
, "SyslogLevel")) {
1153 r
= sd_bus_message_read(message
, "i", &level
);
1157 if (!log_level_is_valid(level
))
1158 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log level value out of range");
1160 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1161 c
->syslog_priority
= (c
->syslog_priority
& LOG_FACMASK
) | level
;
1162 unit_write_settingf(u
, flags
, name
, "SyslogLevel=%i", level
);
1166 } else if (streq(name
, "SyslogFacility")) {
1169 r
= sd_bus_message_read(message
, "i", &facility
);
1173 if (!log_facility_unshifted_is_valid(facility
))
1174 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log facility value out of range");
1176 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1177 c
->syslog_priority
= (facility
<< 3) | LOG_PRI(c
->syslog_priority
);
1178 unit_write_settingf(u
, flags
, name
, "SyslogFacility=%i", facility
);
1183 } else if (streq(name
, "LogLevelMax")) {
1186 r
= sd_bus_message_read(message
, "i", &level
);
1190 if (!log_level_is_valid(level
))
1191 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Maximum log level value out of range");
1193 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1194 c
->log_level_max
= level
;
1195 unit_write_settingf(u
, flags
, name
, "LogLevelMax=%i", level
);
1200 } else if (streq(name
, "LogExtraFields")) {
1203 r
= sd_bus_message_enter_container(message
, 'a', "ay");
1208 _cleanup_free_
void *copy
= NULL
;
1214 /* Note that we expect a byte array for each field, instead of a string. That's because on the
1215 * lower-level journal fields can actually contain binary data and are not restricted to text,
1216 * and we should not "lose precision" in our types on the way. That said, I am pretty sure
1217 * actually encoding binary data as unit metadata is not a good idea. Hence we actually refuse
1218 * any actual binary data, and only accept UTF-8. This allows us to eventually lift this
1219 * limitation, should a good, valid usecase arise. */
1221 r
= sd_bus_message_read_array(message
, 'y', &p
, &sz
);
1227 if (memchr(p
, 0, sz
))
1228 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field contains zero byte");
1230 eq
= memchr(p
, '=', sz
);
1232 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field contains no '=' character");
1233 if (!journal_field_valid(p
, eq
- (const char*) p
, false))
1234 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field invalid");
1236 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1237 t
= realloc_multiply(c
->log_extra_fields
, sizeof(struct iovec
), c
->n_log_extra_fields
+1);
1240 c
->log_extra_fields
= t
;
1243 copy
= malloc(sz
+ 1);
1247 memcpy(copy
, p
, sz
);
1248 ((uint8_t*) copy
)[sz
] = 0;
1250 if (!utf8_is_valid(copy
))
1251 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field is not valid UTF-8");
1253 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1254 c
->log_extra_fields
[c
->n_log_extra_fields
++] = IOVEC_MAKE(copy
, sz
);
1255 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
, name
, "LogExtraFields=%s", (char*) copy
);
1263 r
= sd_bus_message_exit_container(message
);
1267 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && n
== 0) {
1268 exec_context_free_log_extra_fields(c
);
1269 unit_write_setting(u
, flags
, name
, "LogExtraFields=");
1274 } else if (streq(name
, "SecureBits")) {
1277 r
= sd_bus_message_read(message
, "i", &n
);
1281 if (!secure_bits_is_valid(n
))
1282 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid secure bits");
1284 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1285 _cleanup_free_
char *str
= NULL
;
1288 r
= secure_bits_to_string_alloc(n
, &str
);
1292 unit_write_settingf(u
, flags
, name
, "SecureBits=%s", str
);
1296 } else if (STR_IN_SET(name
, "CapabilityBoundingSet", "AmbientCapabilities")) {
1299 r
= sd_bus_message_read(message
, "t", &n
);
1303 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1304 _cleanup_free_
char *str
= NULL
;
1306 if (streq(name
, "CapabilityBoundingSet"))
1307 c
->capability_bounding_set
= n
;
1308 else /* "AmbientCapabilities" */
1309 c
->capability_ambient_set
= n
;
1311 r
= capability_set_to_string_alloc(n
, &str
);
1315 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, str
);
1320 } else if (streq(name
, "Personality")) {
1324 r
= sd_bus_message_read(message
, "s", &s
);
1328 p
= personality_from_string(s
);
1329 if (p
== PERSONALITY_INVALID
)
1330 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid personality");
1332 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1334 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, s
);
1341 } else if (streq(name
, "SystemCallFilter")) {
1343 _cleanup_strv_free_
char **l
= NULL
;
1345 r
= sd_bus_message_enter_container(message
, 'r', "bas");
1349 r
= sd_bus_message_read(message
, "b", &whitelist
);
1353 r
= sd_bus_message_read_strv(message
, &l
);
1357 r
= sd_bus_message_exit_container(message
);
1361 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1362 _cleanup_free_
char *joined
= NULL
;
1364 if (strv_isempty(l
)) {
1365 c
->syscall_whitelist
= false;
1366 c
->syscall_filter
= hashmap_free(c
->syscall_filter
);
1370 c
->syscall_whitelist
= whitelist
;
1372 r
= hashmap_ensure_allocated(&c
->syscall_filter
, NULL
);
1376 STRV_FOREACH(s
, l
) {
1377 _cleanup_free_
char *n
= NULL
;
1380 r
= parse_syscall_and_errno(*s
, &n
, &e
);
1385 const SyscallFilterSet
*set
;
1388 set
= syscall_filter_set_find(n
);
1392 NULSTR_FOREACH(i
, set
->value
) {
1395 id
= seccomp_syscall_resolve_name(i
);
1396 if (id
== __NR_SCMP_ERROR
)
1399 r
= hashmap_put(c
->syscall_filter
, INT_TO_PTR(id
+ 1), INT_TO_PTR(e
));
1407 id
= seccomp_syscall_resolve_name(n
);
1408 if (id
== __NR_SCMP_ERROR
)
1411 r
= hashmap_put(c
->syscall_filter
, INT_TO_PTR(id
+ 1), INT_TO_PTR(e
));
1418 joined
= strv_join(l
, " ");
1422 unit_write_settingf(u
, flags
, name
, "SystemCallFilter=%s%s", whitelist
? "" : "~", joined
);
1427 } else if (streq(name
, "SystemCallArchitectures")) {
1428 _cleanup_strv_free_
char **l
= NULL
;
1430 r
= sd_bus_message_read_strv(message
, &l
);
1434 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1435 _cleanup_free_
char *joined
= NULL
;
1437 if (strv_isempty(l
))
1438 c
->syscall_archs
= set_free(c
->syscall_archs
);
1442 r
= set_ensure_allocated(&c
->syscall_archs
, NULL
);
1446 STRV_FOREACH(s
, l
) {
1449 r
= seccomp_arch_from_string(*s
, &a
);
1453 r
= set_put(c
->syscall_archs
, UINT32_TO_PTR(a
+ 1));
1460 joined
= strv_join(l
, " ");
1464 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
1469 } else if (streq(name
, "SystemCallErrorNumber")) {
1472 r
= sd_bus_message_read(message
, "i", &n
);
1476 if (n
<= 0 || n
> ERRNO_MAX
)
1477 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid SystemCallErrorNumber");
1479 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1480 c
->syscall_errno
= n
;
1482 unit_write_settingf(u
, flags
, name
, "SystemCallErrorNumber=%d", n
);
1487 } else if (streq(name
, "RestrictAddressFamilies")) {
1489 _cleanup_strv_free_
char **l
= NULL
;
1491 r
= sd_bus_message_enter_container(message
, 'r', "bas");
1495 r
= sd_bus_message_read(message
, "b", &whitelist
);
1499 r
= sd_bus_message_read_strv(message
, &l
);
1503 r
= sd_bus_message_exit_container(message
);
1507 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1508 _cleanup_free_
char *joined
= NULL
;
1510 if (strv_isempty(l
)) {
1511 c
->address_families_whitelist
= false;
1512 c
->address_families
= set_free(c
->address_families
);
1516 c
->address_families_whitelist
= whitelist
;
1518 r
= set_ensure_allocated(&c
->address_families
, NULL
);
1522 STRV_FOREACH(s
, l
) {
1525 af
= af_from_name(*s
);
1529 r
= set_put(c
->address_families
, INT_TO_PTR(af
));
1535 joined
= strv_join(l
, " ");
1539 unit_write_settingf(u
, flags
, name
, "RestrictAddressFamilies=%s%s", whitelist
? "" : "~", joined
);
1545 } else if (streq(name
, "CPUSchedulingPolicy")) {
1548 r
= sd_bus_message_read(message
, "i", &n
);
1552 if (!sched_policy_is_valid(n
))
1553 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid CPU scheduling policy");
1555 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1556 _cleanup_free_
char *str
= NULL
;
1558 c
->cpu_sched_policy
= n
;
1559 r
= sched_policy_to_string_alloc(n
, &str
);
1563 unit_write_settingf(u
, flags
, name
, "CPUSchedulingPolicy=%s", str
);
1568 } else if (streq(name
, "CPUSchedulingPriority")) {
1571 r
= sd_bus_message_read(message
, "i", &n
);
1575 if (!ioprio_priority_is_valid(n
))
1576 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid CPU scheduling priority");
1578 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1579 c
->cpu_sched_priority
= n
;
1580 unit_write_settingf(u
, flags
, name
, "CPUSchedulingPriority=%i", n
);
1585 } else if (streq(name
, "CPUAffinity")) {
1589 r
= sd_bus_message_read_array(message
, 'y', &a
, &n
);
1593 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1595 c
->cpuset
= cpu_set_mfree(c
->cpuset
);
1596 c
->cpuset_ncpus
= 0;
1597 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1599 _cleanup_free_
char *str
= NULL
;
1600 size_t allocated
= 0, len
= 0, i
, ncpus
;
1602 ncpus
= CPU_SIZE_TO_NUM(n
);
1604 for (i
= 0; i
< ncpus
; i
++) {
1605 _cleanup_free_
char *p
= NULL
;
1608 if (!CPU_ISSET_S(i
, n
, (cpu_set_t
*) a
))
1611 r
= asprintf(&p
, "%zu", i
);
1617 if (!GREEDY_REALLOC(str
, allocated
, len
+ add
+ 2))
1620 strcpy(mempcpy(str
+ len
, p
, add
), " ");
1625 str
[len
- 1] = '\0';
1627 if (!c
->cpuset
|| c
->cpuset_ncpus
< ncpus
) {
1630 cpuset
= CPU_ALLOC(ncpus
);
1634 CPU_ZERO_S(n
, cpuset
);
1636 CPU_OR_S(CPU_ALLOC_SIZE(c
->cpuset_ncpus
), cpuset
, c
->cpuset
, (cpu_set_t
*) a
);
1637 CPU_FREE(c
->cpuset
);
1639 CPU_OR_S(n
, cpuset
, cpuset
, (cpu_set_t
*) a
);
1642 c
->cpuset_ncpus
= ncpus
;
1644 CPU_OR_S(n
, c
->cpuset
, c
->cpuset
, (cpu_set_t
*) a
);
1646 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, str
);
1651 } else if (streq(name
, "Nice")) {
1654 r
= sd_bus_message_read(message
, "i", &n
);
1658 if (!nice_is_valid(n
))
1659 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Nice value out of range");
1661 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1663 unit_write_settingf(u
, flags
, name
, "Nice=%i", n
);
1668 } else if (streq(name
, "IOSchedulingClass")) {
1671 r
= sd_bus_message_read(message
, "i", &q
);
1675 if (!ioprio_class_is_valid(q
))
1676 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid IO scheduling class: %i", q
);
1678 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1679 _cleanup_free_
char *s
= NULL
;
1681 r
= ioprio_class_to_string_alloc(q
, &s
);
1685 c
->ioprio
= IOPRIO_PRIO_VALUE(q
, IOPRIO_PRIO_DATA(c
->ioprio
));
1686 c
->ioprio_set
= true;
1688 unit_write_settingf(u
, flags
, name
, "IOSchedulingClass=%s", s
);
1693 } else if (streq(name
, "IOSchedulingPriority")) {
1696 r
= sd_bus_message_read(message
, "i", &p
);
1700 if (!ioprio_priority_is_valid(p
))
1701 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid IO scheduling priority: %i", p
);
1703 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1704 c
->ioprio
= IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c
->ioprio
), p
);
1705 c
->ioprio_set
= true;
1707 unit_write_settingf(u
, flags
, name
, "IOSchedulingPriority=%i", p
);
1712 } else if (STR_IN_SET(name
, "TTYPath", "RootDirectory", "RootImage")) {
1715 r
= sd_bus_message_read(message
, "s", &s
);
1719 if (!path_is_absolute(s
))
1720 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s takes an absolute path", name
);
1722 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1723 if (streq(name
, "TTYPath"))
1724 r
= free_and_strdup(&c
->tty_path
, s
);
1725 else if (streq(name
, "RootImage"))
1726 r
= free_and_strdup(&c
->root_image
, s
);
1728 assert(streq(name
, "RootDirectory"));
1729 r
= free_and_strdup(&c
->root_directory
, s
);
1734 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s", name
, s
);
1739 } else if (streq(name
, "WorkingDirectory")) {
1743 r
= sd_bus_message_read(message
, "s", &s
);
1753 if (!streq(s
, "~") && !path_is_absolute(s
))
1754 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
1756 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1757 if (streq(s
, "~")) {
1758 c
->working_directory
= mfree(c
->working_directory
);
1759 c
->working_directory_home
= true;
1761 r
= free_and_strdup(&c
->working_directory
, s
);
1765 c
->working_directory_home
= false;
1768 c
->working_directory_missing_ok
= missing_ok
;
1769 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
1774 } else if (streq(name
, "StandardInput")) {
1778 r
= sd_bus_message_read(message
, "s", &s
);
1782 p
= exec_input_from_string(s
);
1784 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard input name");
1786 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1789 unit_write_settingf(u
, flags
, name
, "StandardInput=%s", exec_input_to_string(p
));
1794 } else if (streq(name
, "StandardOutput")) {
1798 r
= sd_bus_message_read(message
, "s", &s
);
1802 p
= exec_output_from_string(s
);
1804 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard output name");
1806 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1809 unit_write_settingf(u
, flags
, name
, "StandardOutput=%s", exec_output_to_string(p
));
1814 } else if (streq(name
, "StandardError")) {
1818 r
= sd_bus_message_read(message
, "s", &s
);
1822 p
= exec_output_from_string(s
);
1824 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard error name");
1826 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1829 unit_write_settingf(u
, flags
, name
, "StandardError=%s", exec_output_to_string(p
));
1834 } else if (STR_IN_SET(name
,
1835 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
1838 r
= sd_bus_message_read(message
, "s", &s
);
1844 else if (!fdname_is_valid(s
))
1845 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid file descriptor name");
1847 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1849 if (streq(name
, "StandardInputFileDescriptorName")) {
1850 r
= free_and_strdup(c
->stdio_fdname
+ STDIN_FILENO
, s
);
1854 c
->std_input
= EXEC_INPUT_NAMED_FD
;
1855 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardInput=fd:%s", exec_context_fdname(c
, STDIN_FILENO
));
1857 } else if (streq(name
, "StandardOutputFileDescriptorName")) {
1858 r
= free_and_strdup(c
->stdio_fdname
+ STDOUT_FILENO
, s
);
1862 c
->std_output
= EXEC_OUTPUT_NAMED_FD
;
1863 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardOutput=fd:%s", exec_context_fdname(c
, STDOUT_FILENO
));
1866 assert(streq(name
, "StandardErrorFileDescriptorName"));
1868 r
= free_and_strdup(&c
->stdio_fdname
[STDERR_FILENO
], s
);
1872 c
->std_error
= EXEC_OUTPUT_NAMED_FD
;
1873 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardError=fd:%s", exec_context_fdname(c
, STDERR_FILENO
));
1879 } else if (STR_IN_SET(name
, "StandardInputFile", "StandardOutputFile", "StandardErrorFile")) {
1882 r
= sd_bus_message_read(message
, "s", &s
);
1886 if (!path_is_absolute(s
))
1887 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not absolute", s
);
1888 if (!path_is_normalized(s
))
1889 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not normalized", s
);
1891 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1893 if (streq(name
, "StandardInputFile")) {
1894 r
= free_and_strdup(&c
->stdio_file
[STDIN_FILENO
], s
);
1898 c
->std_input
= EXEC_INPUT_FILE
;
1899 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardInput=file:%s", s
);
1901 } else if (streq(name
, "StandardOutputFile")) {
1902 r
= free_and_strdup(&c
->stdio_file
[STDOUT_FILENO
], s
);
1906 c
->std_output
= EXEC_OUTPUT_FILE
;
1907 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardOutput=file:%s", s
);
1910 assert(streq(name
, "StandardErrorFile"));
1912 r
= free_and_strdup(&c
->stdio_file
[STDERR_FILENO
], s
);
1916 c
->std_error
= EXEC_OUTPUT_FILE
;
1917 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardError=file:%s", s
);
1923 } else if (streq(name
, "StandardInputData")) {
1927 r
= sd_bus_message_read_array(message
, 'y', &p
, &sz
);
1931 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1932 _cleanup_free_
char *encoded
= NULL
;
1935 c
->stdin_data
= mfree(c
->stdin_data
);
1936 c
->stdin_data_size
= 0;
1938 unit_write_settingf(u
, flags
, name
, "StandardInputData=");
1943 if (c
->stdin_data_size
+ sz
< c
->stdin_data_size
|| /* check for overflow */
1944 c
->stdin_data_size
+ sz
> EXEC_STDIN_DATA_MAX
)
1947 n
= base64mem(p
, sz
, &encoded
);
1951 q
= realloc(c
->stdin_data
, c
->stdin_data_size
+ sz
);
1955 memcpy((uint8_t*) q
+ c
->stdin_data_size
, p
, sz
);
1958 c
->stdin_data_size
+= sz
;
1960 unit_write_settingf(u
, flags
, name
, "StandardInputData=%s", encoded
);
1966 } else if (STR_IN_SET(name
,
1967 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate",
1968 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers",
1969 "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute",
1970 "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables",
1971 "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS",
1972 "CPUSchedulingResetOnFork", "NonBlocking", "LockPersonality")) {
1975 r
= sd_bus_message_read(message
, "b", &b
);
1979 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1980 if (streq(name
, "IgnoreSIGPIPE"))
1981 c
->ignore_sigpipe
= b
;
1982 else if (streq(name
, "TTYVHangup"))
1984 else if (streq(name
, "TTYReset"))
1986 else if (streq(name
, "TTYVTDisallocate"))
1987 c
->tty_vt_disallocate
= b
;
1988 else if (streq(name
, "PrivateTmp"))
1990 else if (streq(name
, "PrivateDevices"))
1991 c
->private_devices
= b
;
1992 else if (streq(name
, "PrivateNetwork"))
1993 c
->private_network
= b
;
1994 else if (streq(name
, "PrivateUsers"))
1995 c
->private_users
= b
;
1996 else if (streq(name
, "NoNewPrivileges"))
1997 c
->no_new_privileges
= b
;
1998 else if (streq(name
, "SyslogLevelPrefix"))
1999 c
->syslog_level_prefix
= b
;
2000 else if (streq(name
, "MemoryDenyWriteExecute"))
2001 c
->memory_deny_write_execute
= b
;
2002 else if (streq(name
, "RestrictRealtime"))
2003 c
->restrict_realtime
= b
;
2004 else if (streq(name
, "DynamicUser"))
2005 c
->dynamic_user
= b
;
2006 else if (streq(name
, "RemoveIPC"))
2008 else if (streq(name
, "ProtectKernelTunables"))
2009 c
->protect_kernel_tunables
= b
;
2010 else if (streq(name
, "ProtectKernelModules"))
2011 c
->protect_kernel_modules
= b
;
2012 else if (streq(name
, "ProtectControlGroups"))
2013 c
->protect_control_groups
= b
;
2014 else if (streq(name
, "MountAPIVFS"))
2015 c
->mount_apivfs
= b
;
2016 else if (streq(name
, "CPUSchedulingResetOnFork"))
2017 c
->cpu_sched_reset_on_fork
= b
;
2018 else if (streq(name
, "NonBlocking"))
2019 c
->non_blocking
= b
;
2020 else if (streq(name
, "LockPersonality"))
2021 c
->lock_personality
= b
;
2023 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
2028 } else if (streq(name
, "UtmpIdentifier")) {
2031 r
= sd_bus_message_read(message
, "s", &id
);
2035 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2037 r
= free_and_strdup(&c
->utmp_id
, empty_to_null(id
));
2041 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "UtmpIdentifier=%s", strempty(id
));
2046 } else if (streq(name
, "UtmpMode")) {
2050 r
= sd_bus_message_read(message
, "s", &s
);
2054 m
= exec_utmp_mode_from_string(s
);
2056 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid utmp mode");
2058 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2061 unit_write_settingf(u
, flags
, name
, "UtmpMode=%s", exec_utmp_mode_to_string(m
));
2066 } else if (streq(name
, "PAMName")) {
2069 r
= sd_bus_message_read(message
, "s", &n
);
2073 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2075 r
= free_and_strdup(&c
->pam_name
, empty_to_null(n
));
2079 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "PAMName=%s", strempty(n
));
2084 } else if (streq(name
, "Environment")) {
2086 _cleanup_strv_free_
char **l
= NULL
;
2088 r
= sd_bus_message_read_strv(message
, &l
);
2092 if (!strv_env_is_valid(l
))
2093 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
2095 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2096 if (strv_isempty(l
)) {
2097 c
->environment
= strv_free(c
->environment
);
2098 unit_write_setting(u
, flags
, name
, "Environment=");
2100 _cleanup_free_
char *joined
= NULL
;
2103 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
);
2107 e
= strv_env_merge(2, c
->environment
, l
);
2111 strv_free(c
->environment
);
2114 unit_write_settingf(u
, flags
, name
, "Environment=%s", joined
);
2120 } else if (streq(name
, "UnsetEnvironment")) {
2122 _cleanup_strv_free_
char **l
= NULL
;
2124 r
= sd_bus_message_read_strv(message
, &l
);
2128 if (!strv_env_name_or_assignment_is_valid(l
))
2129 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid UnsetEnvironment= list.");
2131 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2132 if (strv_isempty(l
)) {
2133 c
->unset_environment
= strv_free(c
->unset_environment
);
2134 unit_write_setting(u
, flags
, name
, "UnsetEnvironment=");
2136 _cleanup_free_
char *joined
= NULL
;
2139 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
);
2143 e
= strv_env_merge(2, c
->unset_environment
, l
);
2147 strv_free(c
->unset_environment
);
2148 c
->unset_environment
= e
;
2150 unit_write_settingf(u
, flags
, name
, "UnsetEnvironment=%s", joined
);
2156 } else if (streq(name
, "TimerSlackNSec")) {
2160 r
= sd_bus_message_read(message
, "t", &n
);
2164 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2165 c
->timer_slack_nsec
= n
;
2166 unit_write_settingf(u
, flags
, name
, "TimerSlackNSec=" NSEC_FMT
, n
);
2171 } else if (streq(name
, "OOMScoreAdjust")) {
2174 r
= sd_bus_message_read(message
, "i", &oa
);
2178 if (!oom_score_adjust_is_valid(oa
))
2179 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "OOM score adjust value out of range");
2181 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2182 c
->oom_score_adjust
= oa
;
2183 c
->oom_score_adjust_set
= true;
2184 unit_write_settingf(u
, flags
, name
, "OOMScoreAdjust=%i", oa
);
2189 } else if (streq(name
, "EnvironmentFiles")) {
2191 _cleanup_free_
char *joined
= NULL
;
2192 _cleanup_fclose_
FILE *f
= NULL
;
2193 _cleanup_strv_free_
char **l
= NULL
;
2197 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
2201 f
= open_memstream(&joined
, &size
);
2205 fputs("EnvironmentFile=\n", f
);
2207 STRV_FOREACH(i
, c
->environment_files
) {
2208 _cleanup_free_
char *q
= NULL
;
2210 q
= specifier_escape(*i
);
2214 fprintf(f
, "EnvironmentFile=%s\n", q
);
2217 while ((r
= sd_bus_message_enter_container(message
, 'r', "sb")) > 0) {
2221 r
= sd_bus_message_read(message
, "sb", &path
, &b
);
2225 r
= sd_bus_message_exit_container(message
);
2229 if (!path_is_absolute(path
))
2230 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not absolute.", path
);
2232 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2233 _cleanup_free_
char *q
= NULL
;
2236 buf
= strjoin(b
? "-" : "", path
);
2240 q
= specifier_escape(buf
);
2246 fprintf(f
, "EnvironmentFile=%s\n", q
);
2248 r
= strv_consume(&l
, buf
);
2256 r
= sd_bus_message_exit_container(message
);
2260 r
= fflush_and_check(f
);
2264 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2265 if (strv_isempty(l
)) {
2266 c
->environment_files
= strv_free(c
->environment_files
);
2267 unit_write_setting(u
, flags
, name
, "EnvironmentFile=");
2269 r
= strv_extend_strv(&c
->environment_files
, l
, true);
2273 unit_write_setting(u
, flags
, name
, joined
);
2279 } else if (streq(name
, "PassEnvironment")) {
2281 _cleanup_strv_free_
char **l
= NULL
;
2283 r
= sd_bus_message_read_strv(message
, &l
);
2287 if (!strv_env_name_is_valid(l
))
2288 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid PassEnvironment= block.");
2290 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2291 if (strv_isempty(l
)) {
2292 c
->pass_environment
= strv_free(c
->pass_environment
);
2293 unit_write_setting(u
, flags
, name
, "PassEnvironment=");
2295 _cleanup_free_
char *joined
= NULL
;
2297 r
= strv_extend_strv(&c
->pass_environment
, l
, true);
2301 /* We write just the new settings out to file, with unresolved specifiers. */
2302 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
2306 unit_write_settingf(u
, flags
, name
, "PassEnvironment=%s", joined
);
2312 } else if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
2313 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) {
2314 _cleanup_strv_free_
char **l
= NULL
;
2318 r
= sd_bus_message_read_strv(message
, &l
);
2322 STRV_FOREACH(p
, l
) {
2326 if (!utf8_is_valid(i
))
2327 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
2329 offset
= i
[0] == '-';
2330 offset
+= i
[offset
] == '+';
2331 if (!path_is_absolute(i
+ offset
))
2332 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
2335 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2336 if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadWritePaths"))
2337 dirs
= &c
->read_write_paths
;
2338 else if (STR_IN_SET(name
, "ReadOnlyDirectories", "ReadOnlyPaths"))
2339 dirs
= &c
->read_only_paths
;
2340 else /* "InaccessiblePaths" */
2341 dirs
= &c
->inaccessible_paths
;
2343 if (strv_isempty(l
)) {
2344 *dirs
= strv_free(*dirs
);
2345 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2347 _cleanup_free_
char *joined
= NULL
;
2349 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
2353 r
= strv_extend_strv(dirs
, l
, true);
2357 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
2363 } else if (streq(name
, "ProtectSystem")) {
2367 r
= sd_bus_message_read(message
, "s", &s
);
2371 r
= parse_boolean(s
);
2373 ps
= PROTECT_SYSTEM_YES
;
2375 ps
= PROTECT_SYSTEM_NO
;
2377 ps
= protect_system_from_string(s
);
2379 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect system value");
2382 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2383 c
->protect_system
= ps
;
2384 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, s
);
2389 } else if (streq(name
, "ProtectHome")) {
2393 r
= sd_bus_message_read(message
, "s", &s
);
2397 r
= parse_boolean(s
);
2399 ph
= PROTECT_HOME_YES
;
2401 ph
= PROTECT_HOME_NO
;
2403 ph
= protect_home_from_string(s
);
2405 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse protect home value");
2408 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2409 c
->protect_home
= ph
;
2410 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, s
);
2415 } else if (streq(name
, "KeyringMode")) {
2420 r
= sd_bus_message_read(message
, "s", &s
);
2424 m
= exec_keyring_mode_from_string(s
);
2426 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid keyring mode");
2428 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2429 c
->keyring_mode
= m
;
2431 unit_write_settingf(u
, flags
, name
, "KeyringMode=%s", exec_keyring_mode_to_string(m
));
2436 } else if (streq(name
, "RuntimeDirectoryPreserve")) {
2440 r
= sd_bus_message_read(message
, "s", &s
);
2444 m
= exec_preserve_mode_from_string(s
);
2446 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid preserve mode");
2448 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2449 c
->runtime_directory_preserve_mode
= m
;
2451 unit_write_settingf(u
, flags
, name
, "RuntimeDirectoryPreserve=%s", exec_preserve_mode_to_string(m
));
2456 } else if (STR_IN_SET(name
, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode", "UMask")) {
2459 r
= sd_bus_message_read(message
, "u", &m
);
2463 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2464 ExecDirectoryType i
;
2466 if (streq(name
, "UMask"))
2469 for (i
= 0; i
< _EXEC_DIRECTORY_TYPE_MAX
; i
++)
2470 if (startswith(name
, exec_directory_type_to_string(i
))) {
2471 c
->directories
[i
].mode
= m
;
2475 unit_write_settingf(u
, flags
, name
, "%s=%040o", name
, m
);
2480 } else if (STR_IN_SET(name
, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
2481 _cleanup_strv_free_
char **l
= NULL
;
2484 r
= sd_bus_message_read_strv(message
, &l
);
2488 STRV_FOREACH(p
, l
) {
2489 if (!path_is_normalized(*p
) || path_is_absolute(*p
))
2490 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= path is not valid: %s", name
, *p
);
2493 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2494 char ***dirs
= NULL
;
2495 ExecDirectoryType i
;
2497 for (i
= 0; i
< _EXEC_DIRECTORY_TYPE_MAX
; i
++)
2498 if (streq(name
, exec_directory_type_to_string(i
))) {
2499 dirs
= &c
->directories
[i
].paths
;
2505 if (strv_isempty(l
)) {
2506 *dirs
= strv_free(*dirs
);
2507 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2509 _cleanup_free_
char *joined
= NULL
;
2511 r
= strv_extend_strv(dirs
, l
, true);
2515 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
2519 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
2525 } else if (streq(name
, "SELinuxContext")) {
2527 r
= sd_bus_message_read(message
, "s", &s
);
2531 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2533 c
->selinux_context
= mfree(c
->selinux_context
);
2534 else if (free_and_strdup(&c
->selinux_context
, s
) < 0)
2537 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s", name
, strempty(s
));
2542 } else if (STR_IN_SET(name
, "AppArmorProfile", "SmackProcessLabel")) {
2546 r
= sd_bus_message_enter_container(message
, 'r', "bs");
2550 r
= sd_bus_message_read(message
, "bs", &ignore
, &s
);
2554 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2558 if (streq(name
, "AppArmorProfile")) {
2559 p
= &c
->apparmor_profile
;
2560 b
= &c
->apparmor_profile_ignore
;
2561 } else { /* "SmackProcessLabel" */
2562 p
= &c
->smack_process_label
;
2563 b
= &c
->smack_process_label_ignore
;
2570 if (free_and_strdup(p
, s
) < 0)
2575 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s%s", name
, ignore
? "-" : "", strempty(s
));
2580 } else if (streq(name
, "RestrictNamespaces")) {
2583 r
= sd_bus_message_read(message
, "t", &rf
);
2586 if ((rf
& NAMESPACE_FLAGS_ALL
) != rf
)
2587 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown namespace types");
2589 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2590 _cleanup_free_
char *s
= NULL
;
2592 r
= namespace_flag_to_string_many(rf
, &s
);
2596 c
->restrict_namespaces
= rf
;
2597 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, s
);
2601 } else if (streq(name
, "MountFlags")) {
2604 r
= sd_bus_message_read(message
, "t", &fl
);
2607 if (!IN_SET(fl
, 0, MS_SHARED
, MS_PRIVATE
, MS_SLAVE
))
2608 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown mount propagation flags");
2610 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2611 c
->mount_flags
= fl
;
2613 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, mount_propagation_flags_to_string(fl
));
2617 } else if (STR_IN_SET(name
, "BindPaths", "BindReadOnlyPaths")) {
2618 unsigned empty
= true;
2620 r
= sd_bus_message_enter_container(message
, 'a', "(ssbt)");
2624 while ((r
= sd_bus_message_enter_container(message
, 'r', "ssbt")) > 0) {
2625 const char *source
, *destination
;
2627 uint64_t mount_flags
;
2629 r
= sd_bus_message_read(message
, "ssbt", &source
, &destination
, &ignore_enoent
, &mount_flags
);
2633 r
= sd_bus_message_exit_container(message
);
2637 if (!path_is_absolute(source
))
2638 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is not absolute.", source
);
2639 if (!path_is_absolute(destination
))
2640 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Destination path %s is not absolute.", destination
);
2641 if (!IN_SET(mount_flags
, 0, MS_REC
))
2642 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown mount flags.");
2644 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2645 r
= bind_mount_add(&c
->bind_mounts
, &c
->n_bind_mounts
,
2647 .source
= strdup(source
),
2648 .destination
= strdup(destination
),
2649 .read_only
= !!strstr(name
, "ReadOnly"),
2650 .recursive
= !!(mount_flags
& MS_REC
),
2651 .ignore_enoent
= ignore_enoent
,
2656 unit_write_settingf(
2657 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
,
2660 ignore_enoent
? "-" : "",
2663 (mount_flags
& MS_REC
) ? "rbind" : "norbind");
2671 r
= sd_bus_message_exit_container(message
);
2676 bind_mount_free_many(c
->bind_mounts
, c
->n_bind_mounts
);
2677 c
->bind_mounts
= NULL
;
2678 c
->n_bind_mounts
= 0;
2680 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2686 ri
= rlimit_from_string(name
);
2688 soft
= endswith(name
, "Soft");
2692 n
= strndupa(name
, soft
- name
);
2693 ri
= rlimit_from_string(n
);
2704 r
= sd_bus_message_read(message
, "t", &rl
);
2708 if (rl
== (uint64_t) -1)
2713 if ((uint64_t) x
!= rl
)
2717 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2718 _cleanup_free_
char *f
= NULL
;
2721 if (c
->rlimit
[ri
]) {
2722 nl
= *c
->rlimit
[ri
];
2729 /* When the resource limit is not initialized yet, then assign the value to both fields */
2730 nl
= (struct rlimit
) {
2735 r
= rlimit_format(&nl
, &f
);
2740 *c
->rlimit
[ri
] = nl
;
2742 c
->rlimit
[ri
] = newdup(struct rlimit
, &nl
, 1);
2747 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, f
);