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"
35 #include "dbus-util.h"
37 #include "errno-list.h"
42 #include "hexdecoct.h"
45 #include "journal-util.h"
47 #include "mount-util.h"
48 #include "namespace.h"
49 #include "parse-util.h"
50 #include "path-util.h"
51 #include "process-util.h"
52 #include "rlimit-util.h"
54 #include "seccomp-util.h"
56 #include "securebits-util.h"
57 #include "specifier.h"
59 #include "syslog-util.h"
60 #include "unit-printf.h"
61 #include "user-util.h"
64 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output
, exec_output
, ExecOutput
);
65 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input
, exec_input
, ExecInput
);
67 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode
, exec_utmp_mode
, ExecUtmpMode
);
68 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode
, exec_preserve_mode
, ExecPreserveMode
);
69 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode
, exec_keyring_mode
, ExecKeyringMode
);
71 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home
, protect_home
, ProtectHome
);
72 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system
, protect_system
, ProtectSystem
);
74 static int property_get_environment_files(
77 const char *interface
,
79 sd_bus_message
*reply
,
81 sd_bus_error
*error
) {
83 ExecContext
*c
= userdata
;
91 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
95 STRV_FOREACH(j
, c
->environment_files
) {
98 r
= sd_bus_message_append(reply
, "(sb)", fn
[0] == '-' ? fn
+ 1 : fn
, fn
[0] == '-');
103 return sd_bus_message_close_container(reply
);
106 static int property_get_oom_score_adjust(
109 const char *interface
,
110 const char *property
,
111 sd_bus_message
*reply
,
113 sd_bus_error
*error
) {
116 ExecContext
*c
= userdata
;
123 if (c
->oom_score_adjust_set
)
124 n
= c
->oom_score_adjust
;
126 _cleanup_free_
char *t
= NULL
;
129 if (read_one_line_file("/proc/self/oom_score_adj", &t
) >= 0)
133 return sd_bus_message_append(reply
, "i", n
);
136 static int property_get_nice(
139 const char *interface
,
140 const char *property
,
141 sd_bus_message
*reply
,
143 sd_bus_error
*error
) {
146 ExecContext
*c
= userdata
;
157 n
= getpriority(PRIO_PROCESS
, 0);
162 return sd_bus_message_append(reply
, "i", n
);
165 static int property_get_ioprio(
168 const char *interface
,
169 const char *property
,
170 sd_bus_message
*reply
,
172 sd_bus_error
*error
) {
175 ExecContext
*c
= userdata
;
181 return sd_bus_message_append(reply
, "i", exec_context_get_effective_ioprio(c
));
184 static int property_get_ioprio_class(
187 const char *interface
,
188 const char *property
,
189 sd_bus_message
*reply
,
191 sd_bus_error
*error
) {
194 ExecContext
*c
= userdata
;
200 return sd_bus_message_append(reply
, "i", IOPRIO_PRIO_CLASS(exec_context_get_effective_ioprio(c
)));
203 static int property_get_ioprio_priority(
206 const char *interface
,
207 const char *property
,
208 sd_bus_message
*reply
,
210 sd_bus_error
*error
) {
213 ExecContext
*c
= userdata
;
219 return sd_bus_message_append(reply
, "i", IOPRIO_PRIO_DATA(exec_context_get_effective_ioprio(c
)));
222 static int property_get_cpu_sched_policy(
225 const char *interface
,
226 const char *property
,
227 sd_bus_message
*reply
,
229 sd_bus_error
*error
) {
231 ExecContext
*c
= userdata
;
238 if (c
->cpu_sched_set
)
239 n
= c
->cpu_sched_policy
;
241 n
= sched_getscheduler(0);
246 return sd_bus_message_append(reply
, "i", n
);
249 static int property_get_cpu_sched_priority(
252 const char *interface
,
253 const char *property
,
254 sd_bus_message
*reply
,
256 sd_bus_error
*error
) {
258 ExecContext
*c
= userdata
;
265 if (c
->cpu_sched_set
)
266 n
= c
->cpu_sched_priority
;
268 struct sched_param p
= {};
270 if (sched_getparam(0, &p
) >= 0)
271 n
= p
.sched_priority
;
276 return sd_bus_message_append(reply
, "i", n
);
279 static int property_get_cpu_affinity(
282 const char *interface
,
283 const char *property
,
284 sd_bus_message
*reply
,
286 sd_bus_error
*error
) {
288 ExecContext
*c
= userdata
;
295 return sd_bus_message_append_array(reply
, 'y', c
->cpuset
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
));
297 return sd_bus_message_append_array(reply
, 'y', NULL
, 0);
300 static int property_get_timer_slack_nsec(
303 const char *interface
,
304 const char *property
,
305 sd_bus_message
*reply
,
307 sd_bus_error
*error
) {
309 ExecContext
*c
= userdata
;
316 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
317 u
= (uint64_t) c
->timer_slack_nsec
;
319 u
= (uint64_t) prctl(PR_GET_TIMERSLACK
);
321 return sd_bus_message_append(reply
, "t", u
);
324 static int property_get_capability_bounding_set(
327 const char *interface
,
328 const char *property
,
329 sd_bus_message
*reply
,
331 sd_bus_error
*error
) {
333 ExecContext
*c
= userdata
;
339 return sd_bus_message_append(reply
, "t", c
->capability_bounding_set
);
342 static int property_get_ambient_capabilities(
345 const char *interface
,
346 const char *property
,
347 sd_bus_message
*reply
,
349 sd_bus_error
*error
) {
351 ExecContext
*c
= userdata
;
357 return sd_bus_message_append(reply
, "t", c
->capability_ambient_set
);
360 static int property_get_empty_string(
363 const char *interface
,
364 const char *property
,
365 sd_bus_message
*reply
,
367 sd_bus_error
*error
) {
372 return sd_bus_message_append(reply
, "s", "");
375 static int property_get_syscall_filter(
378 const char *interface
,
379 const char *property
,
380 sd_bus_message
*reply
,
382 sd_bus_error
*error
) {
384 ExecContext
*c
= userdata
;
385 _cleanup_strv_free_
char **l
= NULL
;
397 r
= sd_bus_message_open_container(reply
, 'r', "bas");
401 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
406 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_filter
, i
) {
407 _cleanup_free_
char *name
= NULL
;
408 const char *e
= NULL
;
410 int num
= PTR_TO_INT(val
);
412 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
417 e
= errno_to_name(num
);
419 s
= strjoin(name
, ":", e
);
423 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_temporary_filesystems(
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', "(ss)");
804 for (i
= 0; i
< c
->n_temporary_filesystems
; i
++) {
805 TemporaryFileSystem
*t
= c
->temporary_filesystems
+ i
;
807 r
= sd_bus_message_append(
815 return sd_bus_message_close_container(reply
);
818 static int property_get_log_extra_fields(
821 const char *interface
,
822 const char *property
,
823 sd_bus_message
*reply
,
825 sd_bus_error
*error
) {
827 ExecContext
*c
= userdata
;
836 r
= sd_bus_message_open_container(reply
, 'a', "ay");
840 for (i
= 0; i
< c
->n_log_extra_fields
; i
++) {
841 r
= sd_bus_message_append_array(reply
, 'y', c
->log_extra_fields
[i
].iov_base
, c
->log_extra_fields
[i
].iov_len
);
846 return sd_bus_message_close_container(reply
);
849 const sd_bus_vtable bus_exec_vtable
[] = {
850 SD_BUS_VTABLE_START(0),
851 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
852 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
853 SD_BUS_PROPERTY("PassEnvironment", "as", NULL
, offsetof(ExecContext
, pass_environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
854 SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL
, offsetof(ExecContext
, unset_environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
855 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
856 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
857 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
858 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
859 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
860 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
861 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
862 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
863 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
864 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
865 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
866 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
867 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
868 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
869 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
870 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
871 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
872 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
873 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
874 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
875 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
876 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
877 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
878 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
879 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
880 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
881 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
882 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
883 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
884 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
885 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
886 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
887 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
888 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
889 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
890 SD_BUS_PROPERTY("RootImage", "s", NULL
, offsetof(ExecContext
, root_image
), SD_BUS_VTABLE_PROPERTY_CONST
),
891 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
892 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
893 SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
894 SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
895 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
896 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
897 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
898 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
899 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
900 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
901 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
902 SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_stdio_fdname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
903 SD_BUS_PROPERTY("StandardInputData", "ay", property_get_input_data
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
904 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
905 SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_stdio_fdname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
906 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
907 SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_stdio_fdname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
908 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
909 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
910 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
911 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
912 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
913 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
914 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
915 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
916 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
917 SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int
, offsetof(ExecContext
, log_level_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
918 SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
919 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
920 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
921 SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
922 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
923 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
924 SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool
, offsetof(ExecContext
, dynamic_user
), SD_BUS_VTABLE_PROPERTY_CONST
),
925 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool
, offsetof(ExecContext
, remove_ipc
), SD_BUS_VTABLE_PROPERTY_CONST
),
926 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
927 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
928 SD_BUS_PROPERTY("ReadWritePaths", "as", NULL
, offsetof(ExecContext
, read_write_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
929 SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL
, offsetof(ExecContext
, read_only_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
930 SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL
, offsetof(ExecContext
, inaccessible_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
931 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_flags
), SD_BUS_VTABLE_PROPERTY_CONST
),
932 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
933 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
934 SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_kernel_tunables
), SD_BUS_VTABLE_PROPERTY_CONST
),
935 SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_kernel_modules
), SD_BUS_VTABLE_PROPERTY_CONST
),
936 SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_control_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
937 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
938 SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool
, offsetof(ExecContext
, private_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
939 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
940 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
941 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
942 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
943 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
944 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
945 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
946 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
947 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
948 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
949 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
950 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
951 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
952 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
953 SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool
, offsetof(ExecContext
, lock_personality
), SD_BUS_VTABLE_PROPERTY_CONST
),
954 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
955 SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode
, offsetof(ExecContext
, runtime_directory_preserve_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
956 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_RUNTIME
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
957 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_RUNTIME
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
958 SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_STATE
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
959 SD_BUS_PROPERTY("StateDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_STATE
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
960 SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CACHE
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
961 SD_BUS_PROPERTY("CacheDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CACHE
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
962 SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_LOGS
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
963 SD_BUS_PROPERTY("LogsDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_LOGS
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
964 SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CONFIGURATION
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
965 SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CONFIGURATION
].paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
966 SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool
, offsetof(ExecContext
, memory_deny_write_execute
), SD_BUS_VTABLE_PROPERTY_CONST
),
967 SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool
, offsetof(ExecContext
, restrict_realtime
), SD_BUS_VTABLE_PROPERTY_CONST
),
968 SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong
, offsetof(ExecContext
, restrict_namespaces
), SD_BUS_VTABLE_PROPERTY_CONST
),
969 SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
970 SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
971 SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
972 SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool
, offsetof(ExecContext
, mount_apivfs
), SD_BUS_VTABLE_PROPERTY_CONST
),
973 SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode
, offsetof(ExecContext
, keyring_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
975 /* Obsolete/redundant properties: */
976 SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string
, 0, SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
977 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_paths
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
978 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_paths
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
979 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_paths
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
980 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
985 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
994 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
998 r
= sd_bus_message_append(reply
, "s", c
->path
);
1002 r
= sd_bus_message_append_strv(reply
, c
->argv
);
1006 r
= sd_bus_message_append(reply
, "bttttuii",
1007 !!(c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
),
1008 c
->exec_status
.start_timestamp
.realtime
,
1009 c
->exec_status
.start_timestamp
.monotonic
,
1010 c
->exec_status
.exit_timestamp
.realtime
,
1011 c
->exec_status
.exit_timestamp
.monotonic
,
1012 (uint32_t) c
->exec_status
.pid
,
1013 (int32_t) c
->exec_status
.code
,
1014 (int32_t) c
->exec_status
.status
);
1018 return sd_bus_message_close_container(reply
);
1021 int bus_property_get_exec_command(
1024 const char *interface
,
1025 const char *property
,
1026 sd_bus_message
*reply
,
1028 sd_bus_error
*ret_error
) {
1030 ExecCommand
*c
= (ExecCommand
*) userdata
;
1036 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
1040 r
= append_exec_command(reply
, c
);
1044 return sd_bus_message_close_container(reply
);
1047 int bus_property_get_exec_command_list(
1050 const char *interface
,
1051 const char *property
,
1052 sd_bus_message
*reply
,
1054 sd_bus_error
*ret_error
) {
1056 ExecCommand
*c
= *(ExecCommand
**) userdata
;
1062 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
1066 LIST_FOREACH(command
, c
, c
) {
1067 r
= append_exec_command(reply
, c
);
1072 return sd_bus_message_close_container(reply
);
1075 int bus_set_transient_exec_command(
1078 ExecCommand
**exec_command
,
1079 sd_bus_message
*message
,
1080 UnitWriteFlags flags
,
1081 sd_bus_error
*error
) {
1085 r
= sd_bus_message_enter_container(message
, 'a', "(sasb)");
1089 while ((r
= sd_bus_message_enter_container(message
, 'r', "sasb")) > 0) {
1090 _cleanup_strv_free_
char **argv
= NULL
;
1094 r
= sd_bus_message_read(message
, "s", &path
);
1098 if (!path_is_absolute(path
))
1099 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not absolute.", path
);
1101 r
= sd_bus_message_read_strv(message
, &argv
);
1105 r
= sd_bus_message_read(message
, "b", &b
);
1109 r
= sd_bus_message_exit_container(message
);
1113 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1116 c
= new0(ExecCommand
, 1);
1120 c
->path
= strdup(path
);
1126 c
->argv
= TAKE_PTR(argv
);
1128 c
->flags
= b
? EXEC_COMMAND_IGNORE_FAILURE
: 0;
1130 path_kill_slashes(c
->path
);
1131 exec_command_append_list(exec_command
, c
);
1139 r
= sd_bus_message_exit_container(message
);
1143 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1144 _cleanup_free_
char *buf
= NULL
;
1145 _cleanup_fclose_
FILE *f
= NULL
;
1150 *exec_command
= exec_command_free_list(*exec_command
);
1152 f
= open_memstream(&buf
, &size
);
1156 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1158 fputs("ExecStart=\n", f
);
1160 LIST_FOREACH(command
, c
, *exec_command
) {
1161 _cleanup_free_
char *a
= NULL
, *t
= NULL
;
1164 p
= unit_escape_setting(c
->path
, UNIT_ESCAPE_C
|UNIT_ESCAPE_SPECIFIERS
, &t
);
1168 a
= unit_concat_strv(c
->argv
, UNIT_ESCAPE_C
|UNIT_ESCAPE_SPECIFIERS
);
1172 fprintf(f
, "%s=%s@%s %s\n",
1174 c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
? "-" : "",
1179 r
= fflush_and_check(f
);
1183 unit_write_setting(u
, flags
, name
, buf
);
1189 static int parse_personality(const char *s
, unsigned long *p
) {
1194 v
= personality_from_string(s
);
1195 if (v
== PERSONALITY_INVALID
)
1202 static const char* mount_propagation_flags_to_string_with_check(unsigned long n
) {
1203 if (!IN_SET(n
, 0, MS_SHARED
, MS_PRIVATE
, MS_SLAVE
))
1206 return mount_propagation_flags_to_string(n
);
1209 static BUS_DEFINE_SET_TRANSIENT(nsec
, "t", uint64_t, nsec_t
, NSEC_FMT
);
1210 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level
, "i", int32_t, int, "%" PRIi32
, log_level_is_valid
);
1212 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno
, "i", int32_t, int, "%" PRIi32
, errno_is_valid
);
1214 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(sched_priority
, "i", int32_t, int, "%" PRIi32
, sched_priority_is_valid
);
1215 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(nice
, "i", int32_t, int, "%" PRIi32
, nice_is_valid
);
1216 static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input
, ExecInput
, exec_input_from_string
);
1217 static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output
, ExecOutput
, exec_output_from_string
);
1218 static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode
, ExecUtmpMode
, exec_utmp_mode_from_string
);
1219 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system
, ProtectSystem
, parse_protect_system_or_bool
);
1220 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home
, ProtectHome
, parse_protect_home_or_bool
);
1221 static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode
, ExecKeyringMode
, exec_keyring_mode_from_string
);
1222 static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode
, ExecPreserveMode
, exec_preserve_mode_from_string
);
1223 static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality
, unsigned long, parse_personality
);
1224 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits
, "i", int32_t, int, "%" PRIi32
, secure_bits_to_string_alloc_with_check
);
1225 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability
, "t", uint64_t, uint64_t, "%" PRIu64
, capability_set_to_string_alloc
);
1226 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(sched_policy
, "i", int32_t, int, "%" PRIi32
, sched_policy_to_string_alloc_with_check
);
1227 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag
, "t", uint64_t, unsigned long, "%" PRIu64
, namespace_flag_to_string_many_with_check
);
1228 static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags
, "t", uint64_t, unsigned long, "%" PRIu64
, mount_propagation_flags_to_string_with_check
);
1230 int bus_exec_context_set_transient_property(
1234 sd_bus_message
*message
,
1235 UnitWriteFlags flags
,
1236 sd_bus_error
*error
) {
1238 const char *soft
= NULL
;
1246 flags
|= UNIT_PRIVATE
;
1248 if (streq(name
, "User"))
1249 return bus_set_transient_user(u
, name
, &c
->user
, message
, flags
, error
);
1251 if (streq(name
, "Group"))
1252 return bus_set_transient_user(u
, name
, &c
->group
, message
, flags
, error
);
1254 if (streq(name
, "TTYPath"))
1255 return bus_set_transient_path(u
, name
, &c
->tty_path
, message
, flags
, error
);
1257 if (streq(name
, "RootImage"))
1258 return bus_set_transient_path(u
, name
, &c
->root_image
, message
, flags
, error
);
1260 if (streq(name
, "RootDirectory"))
1261 return bus_set_transient_path(u
, name
, &c
->root_directory
, message
, flags
, error
);
1263 if (streq(name
, "SyslogIdentifier"))
1264 return bus_set_transient_string(u
, name
, &c
->syslog_identifier
, message
, flags
, error
);
1266 if (streq(name
, "LogLevelMax"))
1267 return bus_set_transient_log_level(u
, name
, &c
->log_level_max
, message
, flags
, error
);
1269 if (streq(name
, "CPUSchedulingPriority"))
1270 return bus_set_transient_sched_priority(u
, name
, &c
->cpu_sched_priority
, message
, flags
, error
);
1272 if (streq(name
, "Personality"))
1273 return bus_set_transient_personality(u
, name
, &c
->personality
, message
, flags
, error
);
1275 if (streq(name
, "Nice"))
1276 return bus_set_transient_nice(u
, name
, &c
->nice
, message
, flags
, error
);
1278 if (streq(name
, "StandardInput"))
1279 return bus_set_transient_std_input(u
, name
, &c
->std_input
, message
, flags
, error
);
1281 if (streq(name
, "StandardOutput"))
1282 return bus_set_transient_std_output(u
, name
, &c
->std_output
, message
, flags
, error
);
1284 if (streq(name
, "StandardError"))
1285 return bus_set_transient_std_output(u
, name
, &c
->std_error
, message
, flags
, error
);
1287 if (streq(name
, "IgnoreSIGPIPE"))
1288 return bus_set_transient_bool(u
, name
, &c
->ignore_sigpipe
, message
, flags
, error
);
1290 if (streq(name
, "TTYVHangup"))
1291 return bus_set_transient_bool(u
, name
, &c
->tty_vhangup
, message
, flags
, error
);
1293 if (streq(name
, "TTYReset"))
1294 return bus_set_transient_bool(u
, name
, &c
->tty_reset
, message
, flags
, error
);
1296 if (streq(name
, "TTYVTDisallocate"))
1297 return bus_set_transient_bool(u
, name
, &c
->tty_vt_disallocate
, message
, flags
, error
);
1299 if (streq(name
, "PrivateTmp"))
1300 return bus_set_transient_bool(u
, name
, &c
->private_tmp
, message
, flags
, error
);
1302 if (streq(name
, "PrivateDevices"))
1303 return bus_set_transient_bool(u
, name
, &c
->private_devices
, message
, flags
, error
);
1305 if (streq(name
, "PrivateNetwork"))
1306 return bus_set_transient_bool(u
, name
, &c
->private_network
, message
, flags
, error
);
1308 if (streq(name
, "PrivateUsers"))
1309 return bus_set_transient_bool(u
, name
, &c
->private_users
, message
, flags
, error
);
1311 if (streq(name
, "NoNewPrivileges"))
1312 return bus_set_transient_bool(u
, name
, &c
->no_new_privileges
, message
, flags
, error
);
1314 if (streq(name
, "SyslogLevelPrefix"))
1315 return bus_set_transient_bool(u
, name
, &c
->syslog_level_prefix
, message
, flags
, error
);
1317 if (streq(name
, "MemoryDenyWriteExecute"))
1318 return bus_set_transient_bool(u
, name
, &c
->memory_deny_write_execute
, message
, flags
, error
);
1320 if (streq(name
, "RestrictRealtime"))
1321 return bus_set_transient_bool(u
, name
, &c
->restrict_realtime
, message
, flags
, error
);
1323 if (streq(name
, "DynamicUser"))
1324 return bus_set_transient_bool(u
, name
, &c
->dynamic_user
, message
, flags
, error
);
1326 if (streq(name
, "RemoveIPC"))
1327 return bus_set_transient_bool(u
, name
, &c
->remove_ipc
, message
, flags
, error
);
1329 if (streq(name
, "ProtectKernelTunables"))
1330 return bus_set_transient_bool(u
, name
, &c
->protect_kernel_tunables
, message
, flags
, error
);
1332 if (streq(name
, "ProtectKernelModules"))
1333 return bus_set_transient_bool(u
, name
, &c
->protect_kernel_modules
, message
, flags
, error
);
1335 if (streq(name
, "ProtectControlGroups"))
1336 return bus_set_transient_bool(u
, name
, &c
->protect_control_groups
, message
, flags
, error
);
1338 if (streq(name
, "MountAPIVFS"))
1339 return bus_set_transient_bool(u
, name
, &c
->mount_apivfs
, message
, flags
, error
);
1341 if (streq(name
, "CPUSchedulingResetOnFork"))
1342 return bus_set_transient_bool(u
, name
, &c
->cpu_sched_reset_on_fork
, message
, flags
, error
);
1344 if (streq(name
, "NonBlocking"))
1345 return bus_set_transient_bool(u
, name
, &c
->non_blocking
, message
, flags
, error
);
1347 if (streq(name
, "LockPersonality"))
1348 return bus_set_transient_bool(u
, name
, &c
->lock_personality
, message
, flags
, error
);
1350 if (streq(name
, "UtmpIdentifier"))
1351 return bus_set_transient_string(u
, name
, &c
->utmp_id
, message
, flags
, error
);
1353 if (streq(name
, "UtmpMode"))
1354 return bus_set_transient_utmp_mode(u
, name
, &c
->utmp_mode
, message
, flags
, error
);
1356 if (streq(name
, "PAMName"))
1357 return bus_set_transient_string(u
, name
, &c
->pam_name
, message
, flags
, error
);
1359 if (streq(name
, "TimerSlackNSec"))
1360 return bus_set_transient_nsec(u
, name
, &c
->timer_slack_nsec
, message
, flags
, error
);
1362 if (streq(name
, "ProtectSystem"))
1363 return bus_set_transient_protect_system(u
, name
, &c
->protect_system
, message
, flags
, error
);
1365 if (streq(name
, "ProtectHome"))
1366 return bus_set_transient_protect_home(u
, name
, &c
->protect_home
, message
, flags
, error
);
1368 if (streq(name
, "KeyringMode"))
1369 return bus_set_transient_keyring_mode(u
, name
, &c
->keyring_mode
, message
, flags
, error
);
1371 if (streq(name
, "RuntimeDirectoryPreserve"))
1372 return bus_set_transient_preserve_mode(u
, name
, &c
->runtime_directory_preserve_mode
, message
, flags
, error
);
1374 if (streq(name
, "UMask"))
1375 return bus_set_transient_mode_t(u
, name
, &c
->umask
, message
, flags
, error
);
1377 if (streq(name
, "RuntimeDirectoryMode"))
1378 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_RUNTIME
].mode
, message
, flags
, error
);
1380 if (streq(name
, "StateDirectoryMode"))
1381 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_STATE
].mode
, message
, flags
, error
);
1383 if (streq(name
, "CacheDirectoryMode"))
1384 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_CACHE
].mode
, message
, flags
, error
);
1386 if (streq(name
, "LogsDirectoryMode"))
1387 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_LOGS
].mode
, message
, flags
, error
);
1389 if (streq(name
, "ConfigurationDirectoryMode"))
1390 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_CONFIGURATION
].mode
, message
, flags
, error
);
1392 if (streq(name
, "SELinuxContext"))
1393 return bus_set_transient_string(u
, name
, &c
->selinux_context
, message
, flags
, error
);
1395 if (streq(name
, "SecureBits"))
1396 return bus_set_transient_secure_bits(u
, name
, &c
->secure_bits
, message
, flags
, error
);
1398 if (streq(name
, "CapabilityBoundingSet"))
1399 return bus_set_transient_capability(u
, name
, &c
->capability_bounding_set
, message
, flags
, error
);
1401 if (streq(name
, "AmbientCapabilities"))
1402 return bus_set_transient_capability(u
, name
, &c
->capability_ambient_set
, message
, flags
, error
);
1404 if (streq(name
, "CPUSchedulingPolicy"))
1405 return bus_set_transient_sched_policy(u
, name
, &c
->cpu_sched_policy
, message
, flags
, error
);
1407 if (streq(name
, "RestrictNamespaces"))
1408 return bus_set_transient_namespace_flag(u
, name
, &c
->restrict_namespaces
, message
, flags
, error
);
1410 if (streq(name
, "MountFlags"))
1411 return bus_set_transient_mount_flags(u
, name
, &c
->mount_flags
, message
, flags
, error
);
1413 if (streq(name
, "SupplementaryGroups")) {
1414 _cleanup_strv_free_
char **l
= NULL
;
1417 r
= sd_bus_message_read_strv(message
, &l
);
1421 STRV_FOREACH(p
, l
) {
1422 if (!isempty(*p
) && !valid_user_group_name_or_id(*p
))
1423 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid supplementary group names");
1426 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1427 if (strv_isempty(l
)) {
1428 c
->supplementary_groups
= strv_free(c
->supplementary_groups
);
1429 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1431 _cleanup_free_
char *joined
= NULL
;
1433 r
= strv_extend_strv(&c
->supplementary_groups
, l
, true);
1437 joined
= strv_join(c
->supplementary_groups
, " ");
1441 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s", name
, joined
);
1447 } else if (streq(name
, "SyslogLevel")) {
1450 r
= sd_bus_message_read(message
, "i", &level
);
1454 if (!log_level_is_valid(level
))
1455 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log level value out of range");
1457 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1458 c
->syslog_priority
= (c
->syslog_priority
& LOG_FACMASK
) | level
;
1459 unit_write_settingf(u
, flags
, name
, "SyslogLevel=%i", level
);
1464 } else if (streq(name
, "SyslogFacility")) {
1467 r
= sd_bus_message_read(message
, "i", &facility
);
1471 if (!log_facility_unshifted_is_valid(facility
))
1472 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log facility value out of range");
1474 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1475 c
->syslog_priority
= (facility
<< 3) | LOG_PRI(c
->syslog_priority
);
1476 unit_write_settingf(u
, flags
, name
, "SyslogFacility=%i", facility
);
1481 } else if (streq(name
, "LogExtraFields")) {
1484 r
= sd_bus_message_enter_container(message
, 'a', "ay");
1489 _cleanup_free_
void *copy
= NULL
;
1495 /* Note that we expect a byte array for each field, instead of a string. That's because on the
1496 * lower-level journal fields can actually contain binary data and are not restricted to text,
1497 * and we should not "lose precision" in our types on the way. That said, I am pretty sure
1498 * actually encoding binary data as unit metadata is not a good idea. Hence we actually refuse
1499 * any actual binary data, and only accept UTF-8. This allows us to eventually lift this
1500 * limitation, should a good, valid usecase arise. */
1502 r
= sd_bus_message_read_array(message
, 'y', &p
, &sz
);
1508 if (memchr(p
, 0, sz
))
1509 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field contains zero byte");
1511 eq
= memchr(p
, '=', sz
);
1513 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field contains no '=' character");
1514 if (!journal_field_valid(p
, eq
- (const char*) p
, false))
1515 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field invalid");
1517 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1518 t
= reallocarray(c
->log_extra_fields
, c
->n_log_extra_fields
+1, sizeof(struct iovec
));
1521 c
->log_extra_fields
= t
;
1524 copy
= malloc(sz
+ 1);
1528 memcpy(copy
, p
, sz
);
1529 ((uint8_t*) copy
)[sz
] = 0;
1531 if (!utf8_is_valid(copy
))
1532 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field is not valid UTF-8");
1534 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1535 c
->log_extra_fields
[c
->n_log_extra_fields
++] = IOVEC_MAKE(copy
, sz
);
1536 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
, name
, "LogExtraFields=%s", (char*) copy
);
1544 r
= sd_bus_message_exit_container(message
);
1548 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && n
== 0) {
1549 exec_context_free_log_extra_fields(c
);
1550 unit_write_setting(u
, flags
, name
, "LogExtraFields=");
1558 if (streq(name
, "SystemCallErrorNumber"))
1559 return bus_set_transient_errno(u
, name
, &c
->syscall_errno
, message
, flags
, error
);
1561 if (streq(name
, "SystemCallFilter")) {
1563 _cleanup_strv_free_
char **l
= NULL
;
1565 r
= sd_bus_message_enter_container(message
, 'r', "bas");
1569 r
= sd_bus_message_read(message
, "b", &whitelist
);
1573 r
= sd_bus_message_read_strv(message
, &l
);
1577 r
= sd_bus_message_exit_container(message
);
1581 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1582 _cleanup_free_
char *joined
= NULL
;
1583 bool invert
= !whitelist
;
1586 if (strv_isempty(l
)) {
1587 c
->syscall_whitelist
= false;
1588 c
->syscall_filter
= hashmap_free(c
->syscall_filter
);
1590 unit_write_settingf(u
, flags
, name
, "SystemCallFilter=");
1594 if (!c
->syscall_filter
) {
1595 c
->syscall_filter
= hashmap_new(NULL
);
1596 if (!c
->syscall_filter
)
1599 c
->syscall_whitelist
= whitelist
;
1601 if (c
->syscall_whitelist
) {
1602 r
= seccomp_parse_syscall_filter("@default", -1, c
->syscall_filter
, SECCOMP_PARSE_WHITELIST
| (invert
? SECCOMP_PARSE_INVERT
: 0));
1608 STRV_FOREACH(s
, l
) {
1609 _cleanup_free_
char *n
= NULL
;
1612 r
= parse_syscall_and_errno(*s
, &n
, &e
);
1616 r
= seccomp_parse_syscall_filter(n
, e
, c
->syscall_filter
, (invert
? SECCOMP_PARSE_INVERT
: 0) | (c
->syscall_whitelist
? SECCOMP_PARSE_WHITELIST
: 0));
1621 joined
= strv_join(l
, " ");
1625 unit_write_settingf(u
, flags
, name
, "SystemCallFilter=%s%s", whitelist
? "" : "~", joined
);
1630 } else if (streq(name
, "SystemCallArchitectures")) {
1631 _cleanup_strv_free_
char **l
= NULL
;
1633 r
= sd_bus_message_read_strv(message
, &l
);
1637 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1638 _cleanup_free_
char *joined
= NULL
;
1640 if (strv_isempty(l
))
1641 c
->syscall_archs
= set_free(c
->syscall_archs
);
1645 r
= set_ensure_allocated(&c
->syscall_archs
, NULL
);
1649 STRV_FOREACH(s
, l
) {
1652 r
= seccomp_arch_from_string(*s
, &a
);
1656 r
= set_put(c
->syscall_archs
, UINT32_TO_PTR(a
+ 1));
1663 joined
= strv_join(l
, " ");
1667 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
1672 } else if (streq(name
, "RestrictAddressFamilies")) {
1674 _cleanup_strv_free_
char **l
= NULL
;
1676 r
= sd_bus_message_enter_container(message
, 'r', "bas");
1680 r
= sd_bus_message_read(message
, "b", &whitelist
);
1684 r
= sd_bus_message_read_strv(message
, &l
);
1688 r
= sd_bus_message_exit_container(message
);
1692 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1693 _cleanup_free_
char *joined
= NULL
;
1694 bool invert
= !whitelist
;
1697 if (strv_isempty(l
)) {
1698 c
->address_families_whitelist
= false;
1699 c
->address_families
= set_free(c
->address_families
);
1701 unit_write_settingf(u
, flags
, name
, "RestrictAddressFamilies=");
1705 if (!c
->address_families
) {
1706 c
->address_families
= set_new(NULL
);
1707 if (!c
->address_families
)
1710 c
->address_families_whitelist
= whitelist
;
1713 STRV_FOREACH(s
, l
) {
1716 af
= af_from_name(*s
);
1720 if (!invert
== c
->address_families_whitelist
) {
1721 r
= set_put(c
->address_families
, INT_TO_PTR(af
));
1725 (void) set_remove(c
->address_families
, INT_TO_PTR(af
));
1728 joined
= strv_join(l
, " ");
1732 unit_write_settingf(u
, flags
, name
, "RestrictAddressFamilies=%s%s", whitelist
? "" : "~", joined
);
1738 if (streq(name
, "CPUAffinity")) {
1742 r
= sd_bus_message_read_array(message
, 'y', &a
, &n
);
1746 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1748 c
->cpuset
= cpu_set_mfree(c
->cpuset
);
1749 c
->cpuset_ncpus
= 0;
1750 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1752 _cleanup_free_
char *str
= NULL
;
1753 size_t allocated
= 0, len
= 0, i
, ncpus
;
1755 ncpus
= CPU_SIZE_TO_NUM(n
);
1757 for (i
= 0; i
< ncpus
; i
++) {
1758 _cleanup_free_
char *p
= NULL
;
1761 if (!CPU_ISSET_S(i
, n
, (cpu_set_t
*) a
))
1764 r
= asprintf(&p
, "%zu", i
);
1770 if (!GREEDY_REALLOC(str
, allocated
, len
+ add
+ 2))
1773 strcpy(mempcpy(str
+ len
, p
, add
), " ");
1778 str
[len
- 1] = '\0';
1780 if (!c
->cpuset
|| c
->cpuset_ncpus
< ncpus
) {
1783 cpuset
= CPU_ALLOC(ncpus
);
1787 CPU_ZERO_S(n
, cpuset
);
1789 CPU_OR_S(CPU_ALLOC_SIZE(c
->cpuset_ncpus
), cpuset
, c
->cpuset
, (cpu_set_t
*) a
);
1790 CPU_FREE(c
->cpuset
);
1792 CPU_OR_S(n
, cpuset
, cpuset
, (cpu_set_t
*) a
);
1795 c
->cpuset_ncpus
= ncpus
;
1797 CPU_OR_S(n
, c
->cpuset
, c
->cpuset
, (cpu_set_t
*) a
);
1799 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, str
);
1805 } else if (streq(name
, "IOSchedulingClass")) {
1808 r
= sd_bus_message_read(message
, "i", &q
);
1812 if (!ioprio_class_is_valid(q
))
1813 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid IO scheduling class: %i", q
);
1815 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1816 _cleanup_free_
char *s
= NULL
;
1818 r
= ioprio_class_to_string_alloc(q
, &s
);
1822 c
->ioprio
= IOPRIO_PRIO_VALUE(q
, IOPRIO_PRIO_DATA(c
->ioprio
));
1823 c
->ioprio_set
= true;
1825 unit_write_settingf(u
, flags
, name
, "IOSchedulingClass=%s", s
);
1830 } else if (streq(name
, "IOSchedulingPriority")) {
1833 r
= sd_bus_message_read(message
, "i", &p
);
1837 if (!ioprio_priority_is_valid(p
))
1838 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid IO scheduling priority: %i", p
);
1840 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1841 c
->ioprio
= IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c
->ioprio
), p
);
1842 c
->ioprio_set
= true;
1844 unit_write_settingf(u
, flags
, name
, "IOSchedulingPriority=%i", p
);
1849 } else if (streq(name
, "WorkingDirectory")) {
1853 r
= sd_bus_message_read(message
, "s", &s
);
1863 if (!isempty(s
) && !streq(s
, "~") && !path_is_absolute(s
))
1864 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
1866 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1867 if (streq(s
, "~")) {
1868 c
->working_directory
= mfree(c
->working_directory
);
1869 c
->working_directory_home
= true;
1871 r
= free_and_strdup(&c
->working_directory
, empty_to_null(s
));
1875 c
->working_directory_home
= false;
1878 c
->working_directory_missing_ok
= missing_ok
;
1879 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
1884 } else if (STR_IN_SET(name
,
1885 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
1888 r
= sd_bus_message_read(message
, "s", &s
);
1892 if (!isempty(s
) && !fdname_is_valid(s
))
1893 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid file descriptor name");
1895 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1897 if (streq(name
, "StandardInputFileDescriptorName")) {
1898 r
= free_and_strdup(c
->stdio_fdname
+ STDIN_FILENO
, empty_to_null(s
));
1902 c
->std_input
= EXEC_INPUT_NAMED_FD
;
1903 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardInput=fd:%s", exec_context_fdname(c
, STDIN_FILENO
));
1905 } else if (streq(name
, "StandardOutputFileDescriptorName")) {
1906 r
= free_and_strdup(c
->stdio_fdname
+ STDOUT_FILENO
, empty_to_null(s
));
1910 c
->std_output
= EXEC_OUTPUT_NAMED_FD
;
1911 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardOutput=fd:%s", exec_context_fdname(c
, STDOUT_FILENO
));
1914 assert(streq(name
, "StandardErrorFileDescriptorName"));
1916 r
= free_and_strdup(&c
->stdio_fdname
[STDERR_FILENO
], empty_to_null(s
));
1920 c
->std_error
= EXEC_OUTPUT_NAMED_FD
;
1921 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardError=fd:%s", exec_context_fdname(c
, STDERR_FILENO
));
1927 } else if (STR_IN_SET(name
, "StandardInputFile", "StandardOutputFile", "StandardErrorFile")) {
1930 r
= sd_bus_message_read(message
, "s", &s
);
1935 if (!path_is_absolute(s
))
1936 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not absolute", s
);
1937 if (!path_is_normalized(s
))
1938 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not normalized", s
);
1941 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1943 if (streq(name
, "StandardInputFile")) {
1944 r
= free_and_strdup(&c
->stdio_file
[STDIN_FILENO
], empty_to_null(s
));
1948 c
->std_input
= EXEC_INPUT_FILE
;
1949 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardInput=file:%s", s
);
1951 } else if (streq(name
, "StandardOutputFile")) {
1952 r
= free_and_strdup(&c
->stdio_file
[STDOUT_FILENO
], empty_to_null(s
));
1956 c
->std_output
= EXEC_OUTPUT_FILE
;
1957 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardOutput=file:%s", s
);
1960 assert(streq(name
, "StandardErrorFile"));
1962 r
= free_and_strdup(&c
->stdio_file
[STDERR_FILENO
], empty_to_null(s
));
1966 c
->std_error
= EXEC_OUTPUT_FILE
;
1967 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardError=file:%s", s
);
1973 } else if (streq(name
, "StandardInputData")) {
1977 r
= sd_bus_message_read_array(message
, 'y', &p
, &sz
);
1981 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1982 _cleanup_free_
char *encoded
= NULL
;
1985 c
->stdin_data
= mfree(c
->stdin_data
);
1986 c
->stdin_data_size
= 0;
1988 unit_write_settingf(u
, flags
, name
, "StandardInputData=");
1993 if (c
->stdin_data_size
+ sz
< c
->stdin_data_size
|| /* check for overflow */
1994 c
->stdin_data_size
+ sz
> EXEC_STDIN_DATA_MAX
)
1997 n
= base64mem(p
, sz
, &encoded
);
2001 q
= realloc(c
->stdin_data
, c
->stdin_data_size
+ sz
);
2005 memcpy((uint8_t*) q
+ c
->stdin_data_size
, p
, sz
);
2008 c
->stdin_data_size
+= sz
;
2010 unit_write_settingf(u
, flags
, name
, "StandardInputData=%s", encoded
);
2016 } else if (streq(name
, "Environment")) {
2018 _cleanup_strv_free_
char **l
= NULL
;
2020 r
= sd_bus_message_read_strv(message
, &l
);
2024 if (!strv_env_is_valid(l
))
2025 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
2027 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2028 if (strv_isempty(l
)) {
2029 c
->environment
= strv_free(c
->environment
);
2030 unit_write_setting(u
, flags
, name
, "Environment=");
2032 _cleanup_free_
char *joined
= NULL
;
2035 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
);
2039 e
= strv_env_merge(2, c
->environment
, l
);
2043 strv_free(c
->environment
);
2046 unit_write_settingf(u
, flags
, name
, "Environment=%s", joined
);
2052 } else if (streq(name
, "UnsetEnvironment")) {
2054 _cleanup_strv_free_
char **l
= NULL
;
2056 r
= sd_bus_message_read_strv(message
, &l
);
2060 if (!strv_env_name_or_assignment_is_valid(l
))
2061 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid UnsetEnvironment= list.");
2063 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2064 if (strv_isempty(l
)) {
2065 c
->unset_environment
= strv_free(c
->unset_environment
);
2066 unit_write_setting(u
, flags
, name
, "UnsetEnvironment=");
2068 _cleanup_free_
char *joined
= NULL
;
2071 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
);
2075 e
= strv_env_merge(2, c
->unset_environment
, l
);
2079 strv_free(c
->unset_environment
);
2080 c
->unset_environment
= e
;
2082 unit_write_settingf(u
, flags
, name
, "UnsetEnvironment=%s", joined
);
2088 } else if (streq(name
, "OOMScoreAdjust")) {
2091 r
= sd_bus_message_read(message
, "i", &oa
);
2095 if (!oom_score_adjust_is_valid(oa
))
2096 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "OOM score adjust value out of range");
2098 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2099 c
->oom_score_adjust
= oa
;
2100 c
->oom_score_adjust_set
= true;
2101 unit_write_settingf(u
, flags
, name
, "OOMScoreAdjust=%i", oa
);
2106 } else if (streq(name
, "EnvironmentFiles")) {
2108 _cleanup_free_
char *joined
= NULL
;
2109 _cleanup_fclose_
FILE *f
= NULL
;
2110 _cleanup_strv_free_
char **l
= NULL
;
2114 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
2118 f
= open_memstream(&joined
, &size
);
2122 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
2124 fputs("EnvironmentFile=\n", f
);
2126 STRV_FOREACH(i
, c
->environment_files
) {
2127 _cleanup_free_
char *q
= NULL
;
2129 q
= specifier_escape(*i
);
2133 fprintf(f
, "EnvironmentFile=%s\n", q
);
2136 while ((r
= sd_bus_message_enter_container(message
, 'r', "sb")) > 0) {
2140 r
= sd_bus_message_read(message
, "sb", &path
, &b
);
2144 r
= sd_bus_message_exit_container(message
);
2148 if (!path_is_absolute(path
))
2149 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not absolute.", path
);
2151 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2152 _cleanup_free_
char *q
= NULL
;
2155 buf
= strjoin(b
? "-" : "", path
);
2159 q
= specifier_escape(buf
);
2165 fprintf(f
, "EnvironmentFile=%s\n", q
);
2167 r
= strv_consume(&l
, buf
);
2175 r
= sd_bus_message_exit_container(message
);
2179 r
= fflush_and_check(f
);
2183 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2184 if (strv_isempty(l
)) {
2185 c
->environment_files
= strv_free(c
->environment_files
);
2186 unit_write_setting(u
, flags
, name
, "EnvironmentFile=");
2188 r
= strv_extend_strv(&c
->environment_files
, l
, true);
2192 unit_write_setting(u
, flags
, name
, joined
);
2198 } else if (streq(name
, "PassEnvironment")) {
2200 _cleanup_strv_free_
char **l
= NULL
;
2202 r
= sd_bus_message_read_strv(message
, &l
);
2206 if (!strv_env_name_is_valid(l
))
2207 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid PassEnvironment= block.");
2209 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2210 if (strv_isempty(l
)) {
2211 c
->pass_environment
= strv_free(c
->pass_environment
);
2212 unit_write_setting(u
, flags
, name
, "PassEnvironment=");
2214 _cleanup_free_
char *joined
= NULL
;
2216 r
= strv_extend_strv(&c
->pass_environment
, l
, true);
2220 /* We write just the new settings out to file, with unresolved specifiers. */
2221 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
2225 unit_write_settingf(u
, flags
, name
, "PassEnvironment=%s", joined
);
2231 } else if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
2232 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) {
2233 _cleanup_strv_free_
char **l
= NULL
;
2237 r
= sd_bus_message_read_strv(message
, &l
);
2241 STRV_FOREACH(p
, l
) {
2245 offset
= i
[0] == '-';
2246 offset
+= i
[offset
] == '+';
2247 if (!path_is_absolute(i
+ offset
))
2248 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
2250 path_kill_slashes(i
+ offset
);
2253 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2254 if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadWritePaths"))
2255 dirs
= &c
->read_write_paths
;
2256 else if (STR_IN_SET(name
, "ReadOnlyDirectories", "ReadOnlyPaths"))
2257 dirs
= &c
->read_only_paths
;
2258 else /* "InaccessiblePaths" */
2259 dirs
= &c
->inaccessible_paths
;
2261 if (strv_isempty(l
)) {
2262 *dirs
= strv_free(*dirs
);
2263 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2265 _cleanup_free_
char *joined
= NULL
;
2267 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
2271 r
= strv_extend_strv(dirs
, l
, true);
2275 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
2281 } else if (STR_IN_SET(name
, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
2282 _cleanup_strv_free_
char **l
= NULL
;
2285 r
= sd_bus_message_read_strv(message
, &l
);
2289 STRV_FOREACH(p
, l
) {
2290 if (!path_is_normalized(*p
) || path_is_absolute(*p
))
2291 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= path is not valid: %s", name
, *p
);
2294 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2295 char ***dirs
= NULL
;
2296 ExecDirectoryType i
;
2298 for (i
= 0; i
< _EXEC_DIRECTORY_TYPE_MAX
; i
++)
2299 if (streq(name
, exec_directory_type_to_string(i
))) {
2300 dirs
= &c
->directories
[i
].paths
;
2306 if (strv_isempty(l
)) {
2307 *dirs
= strv_free(*dirs
);
2308 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2310 _cleanup_free_
char *joined
= NULL
;
2312 r
= strv_extend_strv(dirs
, l
, true);
2316 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
2320 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
2326 } else if (STR_IN_SET(name
, "AppArmorProfile", "SmackProcessLabel")) {
2330 r
= sd_bus_message_read(message
, "(bs)", &ignore
, &s
);
2334 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2338 if (streq(name
, "AppArmorProfile")) {
2339 p
= &c
->apparmor_profile
;
2340 b
= &c
->apparmor_profile_ignore
;
2341 } else { /* "SmackProcessLabel" */
2342 p
= &c
->smack_process_label
;
2343 b
= &c
->smack_process_label_ignore
;
2350 if (free_and_strdup(p
, s
) < 0)
2355 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s%s", name
, ignore
? "-" : "", strempty(s
));
2360 } else if (STR_IN_SET(name
, "BindPaths", "BindReadOnlyPaths")) {
2361 const char *source
, *destination
;
2363 uint64_t mount_flags
;
2366 r
= sd_bus_message_enter_container(message
, 'a', "(ssbt)");
2370 while ((r
= sd_bus_message_read(message
, "(ssbt)", &source
, &destination
, &ignore_enoent
, &mount_flags
)) > 0) {
2372 if (!path_is_absolute(source
))
2373 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is not absolute.", source
);
2374 if (!path_is_absolute(destination
))
2375 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Destination path %s is not absolute.", destination
);
2376 if (!IN_SET(mount_flags
, 0, MS_REC
))
2377 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown mount flags.");
2379 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2380 r
= bind_mount_add(&c
->bind_mounts
, &c
->n_bind_mounts
,
2382 .source
= strdup(source
),
2383 .destination
= strdup(destination
),
2384 .read_only
= !!strstr(name
, "ReadOnly"),
2385 .recursive
= !!(mount_flags
& MS_REC
),
2386 .ignore_enoent
= ignore_enoent
,
2391 unit_write_settingf(
2392 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
,
2395 ignore_enoent
? "-" : "",
2398 (mount_flags
& MS_REC
) ? "rbind" : "norbind");
2406 r
= sd_bus_message_exit_container(message
);
2411 bind_mount_free_many(c
->bind_mounts
, c
->n_bind_mounts
);
2412 c
->bind_mounts
= NULL
;
2413 c
->n_bind_mounts
= 0;
2415 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2420 } else if (streq(name
, "TemporaryFileSystem")) {
2421 const char *path
, *options
;
2424 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
2428 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &options
)) > 0) {
2430 if (!path_is_absolute(path
))
2431 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Mount point %s is not absolute.", path
);
2433 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2434 r
= temporary_filesystem_add(&c
->temporary_filesystems
, &c
->n_temporary_filesystems
, path
, options
);
2438 unit_write_settingf(
2439 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
,
2451 r
= sd_bus_message_exit_container(message
);
2456 temporary_filesystem_free_many(c
->temporary_filesystems
, c
->n_temporary_filesystems
);
2457 c
->temporary_filesystems
= NULL
;
2458 c
->n_temporary_filesystems
= 0;
2460 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2466 ri
= rlimit_from_string(name
);
2468 soft
= endswith(name
, "Soft");
2472 n
= strndupa(name
, soft
- name
);
2473 ri
= rlimit_from_string(n
);
2484 r
= sd_bus_message_read(message
, "t", &rl
);
2488 if (rl
== (uint64_t) -1)
2493 if ((uint64_t) x
!= rl
)
2497 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2498 _cleanup_free_
char *f
= NULL
;
2501 if (c
->rlimit
[ri
]) {
2502 nl
= *c
->rlimit
[ri
];
2509 /* When the resource limit is not initialized yet, then assign the value to both fields */
2510 nl
= (struct rlimit
) {
2515 r
= rlimit_format(&nl
, &f
);
2520 *c
->rlimit
[ri
] = nl
;
2522 c
->rlimit
[ri
] = newdup(struct rlimit
, &nl
, 1);
2527 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, f
);