1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "alloc-util.h"
7 #include "bus-get-properties.h"
10 #include "capability-util.h"
11 #include "cpu-set-util.h"
12 #include "creds-util.h"
13 #include "dbus-execute.h"
14 #include "dbus-util.h"
16 #include "errno-list.h"
18 #include "exec-credential.h"
22 #include "hexdecoct.h"
23 #include "iovec-util.h"
24 #include "ioprio-util.h"
25 #include "journal-file.h"
26 #include "load-fragment.h"
27 #include "memstream-util.h"
28 #include "missing_ioprio.h"
29 #include "mountpoint-util.h"
30 #include "namespace.h"
31 #include "parse-util.h"
32 #include "path-util.h"
33 #include "pcre2-util.h"
34 #include "process-util.h"
35 #include "rlimit-util.h"
36 #include "seccomp-util.h"
37 #include "securebits-util.h"
38 #include "specifier.h"
39 #include "stat-util.h"
41 #include "syslog-util.h"
42 #include "unit-printf.h"
43 #include "user-util.h"
46 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output
, exec_output
, ExecOutput
);
47 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input
, exec_input
, ExecInput
);
48 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode
, exec_utmp_mode
, ExecUtmpMode
);
49 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_preserve_mode
, exec_preserve_mode
, ExecPreserveMode
);
50 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode
, exec_keyring_mode
, ExecKeyringMode
);
51 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_proc
, protect_proc
, ProtectProc
);
52 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_proc_subset
, proc_subset
, ProcSubset
);
53 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_home
, protect_home
, ProtectHome
);
54 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system
, protect_system
, ProtectSystem
);
55 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality
, personality
, unsigned long);
56 static BUS_DEFINE_PROPERTY_GET(property_get_ioprio
, "i", ExecContext
, exec_context_get_effective_ioprio
);
57 static BUS_DEFINE_PROPERTY_GET(property_get_mount_apivfs
, "b", ExecContext
, exec_context_get_effective_mount_apivfs
);
58 static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_class
, "i", ExecContext
, exec_context_get_effective_ioprio
, ioprio_prio_class
);
59 static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority
, "i", ExecContext
, exec_context_get_effective_ioprio
, ioprio_prio_data
);
60 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string
, "s", NULL
);
61 static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level
, "i", int, LOG_PRI
);
62 static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility
, "i", int, LOG_FAC
);
63 static BUS_DEFINE_PROPERTY_GET(property_get_cpu_affinity_from_numa
, "b", ExecContext
, exec_context_get_cpu_affinity_from_numa
);
64 static BUS_DEFINE_PROPERTY_GET(property_get_oom_score_adjust
, "i", ExecContext
, exec_context_get_oom_score_adjust
);
65 static BUS_DEFINE_PROPERTY_GET(property_get_nice
, "i", ExecContext
, exec_context_get_nice
);
66 static BUS_DEFINE_PROPERTY_GET(property_get_cpu_sched_policy
, "i", ExecContext
, exec_context_get_cpu_sched_policy
);
67 static BUS_DEFINE_PROPERTY_GET(property_get_cpu_sched_priority
, "i", ExecContext
, exec_context_get_cpu_sched_priority
);
68 static BUS_DEFINE_PROPERTY_GET(property_get_coredump_filter
, "t", ExecContext
, exec_context_get_coredump_filter
);
69 static BUS_DEFINE_PROPERTY_GET(property_get_timer_slack_nsec
, "t", ExecContext
, exec_context_get_timer_slack_nsec
);
70 static BUS_DEFINE_PROPERTY_GET(property_get_set_login_environment
, "b", ExecContext
, exec_context_get_set_login_environment
);
72 static int property_get_environment_files(
75 const char *interface
,
77 sd_bus_message
*reply
,
79 sd_bus_error
*error
) {
81 ExecContext
*c
= ASSERT_PTR(userdata
);
87 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
91 STRV_FOREACH(j
, c
->environment_files
) {
94 r
= sd_bus_message_append(reply
, "(sb)", fn
[0] == '-' ? fn
+ 1 : fn
, fn
[0] == '-');
99 return sd_bus_message_close_container(reply
);
102 static int property_get_cpu_affinity(
105 const char *interface
,
106 const char *property
,
107 sd_bus_message
*reply
,
109 sd_bus_error
*error
) {
111 ExecContext
*c
= ASSERT_PTR(userdata
);
112 _cleanup_(cpu_set_reset
) CPUSet s
= {};
113 _cleanup_free_
uint8_t *array
= NULL
;
119 if (c
->cpu_affinity_from_numa
) {
122 r
= numa_to_cpu_set(&c
->numa_policy
, &s
);
127 (void) cpu_set_to_dbus(c
->cpu_affinity_from_numa
? &s
: &c
->cpu_set
, &array
, &allocated
);
129 return sd_bus_message_append_array(reply
, 'y', array
, allocated
);
132 static int property_get_numa_mask(
135 const char *interface
,
136 const char *property
,
137 sd_bus_message
*reply
,
139 sd_bus_error
*error
) {
141 ExecContext
*c
= ASSERT_PTR(userdata
);
142 _cleanup_free_
uint8_t *array
= NULL
;
148 (void) cpu_set_to_dbus(&c
->numa_policy
.nodes
, &array
, &allocated
);
150 return sd_bus_message_append_array(reply
, 'y', array
, allocated
);
153 static int property_get_numa_policy(
156 const char *interface
,
157 const char *property
,
158 sd_bus_message
*reply
,
160 sd_bus_error
*error
) {
161 ExecContext
*c
= ASSERT_PTR(userdata
);
167 policy
= numa_policy_get_type(&c
->numa_policy
);
169 return sd_bus_message_append_basic(reply
, 'i', &policy
);
172 static int property_get_syscall_filter(
175 const char *interface
,
176 const char *property
,
177 sd_bus_message
*reply
,
179 sd_bus_error
*error
) {
181 ExecContext
*c
= ASSERT_PTR(userdata
);
182 _cleanup_strv_free_
char **l
= NULL
;
188 r
= sd_bus_message_open_container(reply
, 'r', "bas");
192 r
= sd_bus_message_append(reply
, "b", c
->syscall_allow_list
);
196 l
= exec_context_get_syscall_filter(c
);
200 r
= sd_bus_message_append_strv(reply
, l
);
204 return sd_bus_message_close_container(reply
);
207 static int property_get_syscall_log(
210 const char *interface
,
211 const char *property
,
212 sd_bus_message
*reply
,
214 sd_bus_error
*error
) {
216 ExecContext
*c
= ASSERT_PTR(userdata
);
217 _cleanup_strv_free_
char **l
= NULL
;
223 r
= sd_bus_message_open_container(reply
, 'r', "bas");
227 r
= sd_bus_message_append(reply
, "b", c
->syscall_log_allow_list
);
231 l
= exec_context_get_syscall_log(c
);
235 r
= sd_bus_message_append_strv(reply
, l
);
239 return sd_bus_message_close_container(reply
);
242 static int property_get_syscall_archs(
245 const char *interface
,
246 const char *property
,
247 sd_bus_message
*reply
,
249 sd_bus_error
*error
) {
251 ExecContext
*c
= ASSERT_PTR(userdata
);
252 _cleanup_strv_free_
char **l
= NULL
;
258 l
= exec_context_get_syscall_archs(c
);
262 r
= sd_bus_message_append_strv(reply
, l
);
269 static int property_get_selinux_context(
272 const char *interface
,
273 const char *property
,
274 sd_bus_message
*reply
,
276 sd_bus_error
*error
) {
278 ExecContext
*c
= ASSERT_PTR(userdata
);
283 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
286 static int property_get_apparmor_profile(
289 const char *interface
,
290 const char *property
,
291 sd_bus_message
*reply
,
293 sd_bus_error
*error
) {
295 ExecContext
*c
= ASSERT_PTR(userdata
);
300 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
303 static int property_get_smack_process_label(
306 const char *interface
,
307 const char *property
,
308 sd_bus_message
*reply
,
310 sd_bus_error
*error
) {
312 ExecContext
*c
= ASSERT_PTR(userdata
);
317 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
320 static int property_get_address_families(
323 const char *interface
,
324 const char *property
,
325 sd_bus_message
*reply
,
327 sd_bus_error
*error
) {
329 ExecContext
*c
= ASSERT_PTR(userdata
);
330 _cleanup_strv_free_
char **l
= NULL
;
336 r
= sd_bus_message_open_container(reply
, 'r', "bas");
340 r
= sd_bus_message_append(reply
, "b", c
->address_families_allow_list
);
344 l
= exec_context_get_address_families(c
);
348 r
= sd_bus_message_append_strv(reply
, l
);
352 return sd_bus_message_close_container(reply
);
355 static int property_get_working_directory(
358 const char *interface
,
359 const char *property
,
360 sd_bus_message
*reply
,
362 sd_bus_error
*error
) {
364 ExecContext
*c
= ASSERT_PTR(userdata
);
370 if (c
->working_directory_home
)
373 wd
= c
->working_directory
;
375 if (c
->working_directory_missing_ok
)
376 wd
= strjoina("!", wd
);
378 return sd_bus_message_append(reply
, "s", wd
);
381 static int property_get_stdio_fdname(
384 const char *interface
,
385 const char *property
,
386 sd_bus_message
*reply
,
388 sd_bus_error
*error
) {
390 ExecContext
*c
= ASSERT_PTR(userdata
);
397 if (streq(property
, "StandardInputFileDescriptorName"))
398 fileno
= STDIN_FILENO
;
399 else if (streq(property
, "StandardOutputFileDescriptorName"))
400 fileno
= STDOUT_FILENO
;
402 assert(streq(property
, "StandardErrorFileDescriptorName"));
403 fileno
= STDERR_FILENO
;
406 return sd_bus_message_append(reply
, "s", exec_context_fdname(c
, fileno
));
409 static int property_get_input_data(
412 const char *interface
,
413 const char *property
,
414 sd_bus_message
*reply
,
416 sd_bus_error
*error
) {
418 ExecContext
*c
= ASSERT_PTR(userdata
);
424 return sd_bus_message_append_array(reply
, 'y', c
->stdin_data
, c
->stdin_data_size
);
427 static int property_get_restrict_filesystems(
430 const char *interface
,
431 const char *property
,
432 sd_bus_message
*reply
,
434 sd_bus_error
*error
) {
436 ExecContext
*c
= ASSERT_PTR(userdata
);
437 _cleanup_free_
char **l
= NULL
;
443 r
= sd_bus_message_open_container(reply
, 'r', "bas");
447 r
= sd_bus_message_append(reply
, "b", c
->restrict_filesystems_allow_list
);
451 l
= exec_context_get_restrict_filesystems(c
);
455 r
= sd_bus_message_append_strv(reply
, l
);
459 return sd_bus_message_close_container(reply
);
462 static int property_get_bind_paths(
465 const char *interface
,
466 const char *property
,
467 sd_bus_message
*reply
,
469 sd_bus_error
*error
) {
471 ExecContext
*c
= ASSERT_PTR(userdata
);
479 ro
= strstr(property
, "ReadOnly");
481 r
= sd_bus_message_open_container(reply
, 'a', "(ssbt)");
485 for (size_t i
= 0; i
< c
->n_bind_mounts
; i
++) {
487 if (ro
!= c
->bind_mounts
[i
].read_only
)
490 r
= sd_bus_message_append(
492 c
->bind_mounts
[i
].source
,
493 c
->bind_mounts
[i
].destination
,
494 c
->bind_mounts
[i
].ignore_enoent
,
495 c
->bind_mounts
[i
].recursive
? (uint64_t) MS_REC
: (uint64_t) 0);
500 return sd_bus_message_close_container(reply
);
503 static int property_get_temporary_filesystems(
506 const char *interface
,
507 const char *property
,
508 sd_bus_message
*reply
,
510 sd_bus_error
*error
) {
512 ExecContext
*c
= ASSERT_PTR(userdata
);
519 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
523 for (unsigned i
= 0; i
< c
->n_temporary_filesystems
; i
++) {
524 TemporaryFileSystem
*t
= c
->temporary_filesystems
+ i
;
526 r
= sd_bus_message_append(
534 return sd_bus_message_close_container(reply
);
537 static int property_get_log_extra_fields(
540 const char *interface
,
541 const char *property
,
542 sd_bus_message
*reply
,
544 sd_bus_error
*error
) {
546 ExecContext
*c
= ASSERT_PTR(userdata
);
553 r
= sd_bus_message_open_container(reply
, 'a', "ay");
557 for (size_t i
= 0; i
< c
->n_log_extra_fields
; i
++) {
558 r
= sd_bus_message_append_array(reply
, 'y', c
->log_extra_fields
[i
].iov_base
, c
->log_extra_fields
[i
].iov_len
);
563 return sd_bus_message_close_container(reply
);
566 static int sd_bus_message_append_log_filter_patterns(sd_bus_message
*reply
, Set
*patterns
, bool is_allowlist
) {
572 SET_FOREACH(pattern
, patterns
) {
573 r
= sd_bus_message_append(reply
, "(bs)", is_allowlist
, pattern
);
581 static int property_get_log_filter_patterns(
584 const char *interface
,
585 const char *property
,
586 sd_bus_message
*reply
,
588 sd_bus_error
*error
) {
590 ExecContext
*c
= userdata
;
596 r
= sd_bus_message_open_container(reply
, 'a', "(bs)");
600 r
= sd_bus_message_append_log_filter_patterns(reply
, c
->log_filter_allowed_patterns
,
601 /* is_allowlist = */ true);
605 r
= sd_bus_message_append_log_filter_patterns(reply
, c
->log_filter_denied_patterns
,
606 /* is_allowlist = */ false);
610 return sd_bus_message_close_container(reply
);
613 static int property_get_set_credential(
616 const char *interface
,
617 const char *property
,
618 sd_bus_message
*reply
,
620 sd_bus_error
*error
) {
622 ExecContext
*c
= ASSERT_PTR(userdata
);
623 ExecSetCredential
*sc
;
630 r
= sd_bus_message_open_container(reply
, 'a', "(say)");
634 HASHMAP_FOREACH(sc
, c
->set_credentials
) {
636 if (sc
->encrypted
!= streq(property
, "SetCredentialEncrypted"))
639 r
= sd_bus_message_open_container(reply
, 'r', "say");
643 r
= sd_bus_message_append(reply
, "s", sc
->id
);
647 r
= sd_bus_message_append_array(reply
, 'y', sc
->data
, sc
->size
);
651 r
= sd_bus_message_close_container(reply
);
656 return sd_bus_message_close_container(reply
);
659 static int property_get_load_credential(
662 const char *interface
,
663 const char *property
,
664 sd_bus_message
*reply
,
666 sd_bus_error
*error
) {
668 ExecContext
*c
= ASSERT_PTR(userdata
);
669 ExecLoadCredential
*lc
;
676 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
680 HASHMAP_FOREACH(lc
, c
->load_credentials
) {
682 if (lc
->encrypted
!= streq(property
, "LoadCredentialEncrypted"))
685 r
= sd_bus_message_append(reply
, "(ss)", lc
->id
, lc
->path
);
690 return sd_bus_message_close_container(reply
);
693 static int property_get_root_hash(
696 const char *interface
,
697 const char *property
,
698 sd_bus_message
*reply
,
700 sd_bus_error
*error
) {
702 ExecContext
*c
= ASSERT_PTR(userdata
);
708 return sd_bus_message_append_array(reply
, 'y', c
->root_hash
, c
->root_hash_size
);
711 static int property_get_root_hash_sig(
714 const char *interface
,
715 const char *property
,
716 sd_bus_message
*reply
,
718 sd_bus_error
*error
) {
720 ExecContext
*c
= ASSERT_PTR(userdata
);
726 return sd_bus_message_append_array(reply
, 'y', c
->root_hash_sig
, c
->root_hash_sig_size
);
729 static int property_get_root_image_options(
732 const char *interface
,
733 const char *property
,
734 sd_bus_message
*reply
,
736 sd_bus_error
*error
) {
738 ExecContext
*c
= ASSERT_PTR(userdata
);
745 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
749 LIST_FOREACH(mount_options
, m
, c
->root_image_options
) {
750 r
= sd_bus_message_append(reply
, "(ss)",
751 partition_designator_to_string(m
->partition_designator
),
757 return sd_bus_message_close_container(reply
);
760 static int property_get_mount_images(
763 const char *interface
,
764 const char *property
,
765 sd_bus_message
*reply
,
767 sd_bus_error
*error
) {
769 ExecContext
*c
= ASSERT_PTR(userdata
);
776 r
= sd_bus_message_open_container(reply
, 'a', "(ssba(ss))");
780 for (size_t i
= 0; i
< c
->n_mount_images
; i
++) {
781 r
= sd_bus_message_open_container(reply
, SD_BUS_TYPE_STRUCT
, "ssba(ss)");
784 r
= sd_bus_message_append(
786 c
->mount_images
[i
].source
,
787 c
->mount_images
[i
].destination
,
788 c
->mount_images
[i
].ignore_enoent
);
791 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
794 LIST_FOREACH(mount_options
, m
, c
->mount_images
[i
].mount_options
) {
795 r
= sd_bus_message_append(reply
, "(ss)",
796 partition_designator_to_string(m
->partition_designator
),
801 r
= sd_bus_message_close_container(reply
);
804 r
= sd_bus_message_close_container(reply
);
809 return sd_bus_message_close_container(reply
);
812 static int property_get_extension_images(
815 const char *interface
,
816 const char *property
,
817 sd_bus_message
*reply
,
819 sd_bus_error
*error
) {
821 ExecContext
*c
= ASSERT_PTR(userdata
);
828 r
= sd_bus_message_open_container(reply
, 'a', "(sba(ss))");
832 for (size_t i
= 0; i
< c
->n_extension_images
; i
++) {
833 r
= sd_bus_message_open_container(reply
, SD_BUS_TYPE_STRUCT
, "sba(ss)");
836 r
= sd_bus_message_append(
838 c
->extension_images
[i
].source
,
839 c
->extension_images
[i
].ignore_enoent
);
842 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
845 LIST_FOREACH(mount_options
, m
, c
->extension_images
[i
].mount_options
) {
846 r
= sd_bus_message_append(reply
, "(ss)",
847 partition_designator_to_string(m
->partition_designator
),
852 r
= sd_bus_message_close_container(reply
);
855 r
= sd_bus_message_close_container(reply
);
860 return sd_bus_message_close_container(reply
);
863 static int bus_property_get_exec_dir(
866 const char *interface
,
867 const char *property
,
868 sd_bus_message
*reply
,
870 sd_bus_error
*error
) {
872 ExecDirectory
*d
= ASSERT_PTR(userdata
);
879 r
= sd_bus_message_open_container(reply
, 'a', "s");
883 for (size_t i
= 0; i
< d
->n_items
; i
++) {
884 r
= sd_bus_message_append_basic(reply
, 's', d
->items
[i
].path
);
889 return sd_bus_message_close_container(reply
);
892 static int bus_property_get_exec_dir_symlink(
895 const char *interface
,
896 const char *property
,
897 sd_bus_message
*reply
,
899 sd_bus_error
*error
) {
901 ExecDirectory
*d
= ASSERT_PTR(userdata
);
908 r
= sd_bus_message_open_container(reply
, 'a', "(sst)");
912 for (size_t i
= 0; i
< d
->n_items
; i
++)
913 STRV_FOREACH(dst
, d
->items
[i
].symlinks
) {
914 r
= sd_bus_message_append(reply
, "(sst)", d
->items
[i
].path
, *dst
, 0 /* flags, unused for now */);
919 return sd_bus_message_close_container(reply
);
922 static int property_get_image_policy(
925 const char *interface
,
926 const char *property
,
927 sd_bus_message
*reply
,
929 sd_bus_error
*error
) {
931 ImagePolicy
**pp
= ASSERT_PTR(userdata
);
932 _cleanup_free_
char *s
= NULL
;
939 r
= image_policy_to_string(*pp
?: &image_policy_service
, /* simplify= */ true, &s
);
943 return sd_bus_message_append(reply
, "s", s
);
946 const sd_bus_vtable bus_exec_vtable
[] = {
947 SD_BUS_VTABLE_START(0),
948 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
949 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
950 SD_BUS_PROPERTY("PassEnvironment", "as", NULL
, offsetof(ExecContext
, pass_environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
951 SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL
, offsetof(ExecContext
, unset_environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
952 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
953 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
954 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
955 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
956 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
957 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
958 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
959 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
960 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
961 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
962 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
963 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
964 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
965 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
966 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
967 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
968 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
969 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
970 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
971 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
972 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
973 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
974 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
975 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
976 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
977 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
978 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
979 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
980 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
981 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
982 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
983 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
984 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
985 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
986 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
987 SD_BUS_PROPERTY("RootImage", "s", NULL
, offsetof(ExecContext
, root_image
), SD_BUS_VTABLE_PROPERTY_CONST
),
988 SD_BUS_PROPERTY("RootImageOptions", "a(ss)", property_get_root_image_options
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
989 SD_BUS_PROPERTY("RootHash", "ay", property_get_root_hash
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
990 SD_BUS_PROPERTY("RootHashPath", "s", NULL
, offsetof(ExecContext
, root_hash_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
991 SD_BUS_PROPERTY("RootHashSignature", "ay", property_get_root_hash_sig
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
992 SD_BUS_PROPERTY("RootHashSignaturePath", "s", NULL
, offsetof(ExecContext
, root_hash_sig_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
993 SD_BUS_PROPERTY("RootVerity", "s", NULL
, offsetof(ExecContext
, root_verity
), SD_BUS_VTABLE_PROPERTY_CONST
),
994 SD_BUS_PROPERTY("RootEphemeral", "b", bus_property_get_bool
, offsetof(ExecContext
, root_ephemeral
), SD_BUS_VTABLE_PROPERTY_CONST
),
995 SD_BUS_PROPERTY("ExtensionDirectories", "as", NULL
, offsetof(ExecContext
, extension_directories
), SD_BUS_VTABLE_PROPERTY_CONST
),
996 SD_BUS_PROPERTY("ExtensionImages", "a(sba(ss))", property_get_extension_images
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
997 SD_BUS_PROPERTY("MountImages", "a(ssba(ss))", property_get_mount_images
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
998 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
999 SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1000 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1001 SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1002 SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1003 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1004 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1005 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1006 SD_BUS_PROPERTY("CPUAffinityFromNUMA", "b", property_get_cpu_affinity_from_numa
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1007 SD_BUS_PROPERTY("NUMAPolicy", "i", property_get_numa_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1008 SD_BUS_PROPERTY("NUMAMask", "ay", property_get_numa_mask
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1009 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1010 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
1011 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
1012 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
1013 SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_stdio_fdname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1014 SD_BUS_PROPERTY("StandardInputData", "ay", property_get_input_data
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1015 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
1016 SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_stdio_fdname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1017 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
1018 SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_stdio_fdname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1019 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
1020 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
1021 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
1022 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
1023 SD_BUS_PROPERTY("TTYRows", "q", bus_property_get_unsigned
, offsetof(ExecContext
, tty_rows
), SD_BUS_VTABLE_PROPERTY_CONST
),
1024 SD_BUS_PROPERTY("TTYColumns", "q", bus_property_get_unsigned
, offsetof(ExecContext
, tty_cols
), SD_BUS_VTABLE_PROPERTY_CONST
),
1025 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
1026 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
1027 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
1028 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
1029 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
1030 SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int
, offsetof(ExecContext
, log_level_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
1031 SD_BUS_PROPERTY("LogRateLimitIntervalUSec", "t", bus_property_get_usec
, offsetof(ExecContext
, log_ratelimit_interval_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
1032 SD_BUS_PROPERTY("LogRateLimitBurst", "u", bus_property_get_unsigned
, offsetof(ExecContext
, log_ratelimit_burst
), SD_BUS_VTABLE_PROPERTY_CONST
),
1033 SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1034 SD_BUS_PROPERTY("LogFilterPatterns", "a(bs)", property_get_log_filter_patterns
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1035 SD_BUS_PROPERTY("LogNamespace", "s", NULL
, offsetof(ExecContext
, log_namespace
), SD_BUS_VTABLE_PROPERTY_CONST
),
1036 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
1037 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", NULL
, offsetof(ExecContext
, capability_bounding_set
), SD_BUS_VTABLE_PROPERTY_CONST
),
1038 SD_BUS_PROPERTY("AmbientCapabilities", "t", NULL
, offsetof(ExecContext
, capability_ambient_set
), SD_BUS_VTABLE_PROPERTY_CONST
),
1039 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
1040 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
1041 SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool
, offsetof(ExecContext
, dynamic_user
), SD_BUS_VTABLE_PROPERTY_CONST
),
1042 SD_BUS_PROPERTY("SetLoginEnvironment", "b", property_get_set_login_environment
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1043 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool
, offsetof(ExecContext
, remove_ipc
), SD_BUS_VTABLE_PROPERTY_CONST
),
1044 SD_BUS_PROPERTY("SetCredential", "a(say)", property_get_set_credential
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1045 SD_BUS_PROPERTY("SetCredentialEncrypted", "a(say)", property_get_set_credential
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1046 SD_BUS_PROPERTY("LoadCredential", "a(ss)", property_get_load_credential
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1047 SD_BUS_PROPERTY("LoadCredentialEncrypted", "a(ss)", property_get_load_credential
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1048 SD_BUS_PROPERTY("ImportCredential", "as", bus_property_get_string_set
, offsetof(ExecContext
, import_credentials
), SD_BUS_VTABLE_PROPERTY_CONST
),
1049 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
1050 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
1051 SD_BUS_PROPERTY("ReadWritePaths", "as", NULL
, offsetof(ExecContext
, read_write_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
1052 SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL
, offsetof(ExecContext
, read_only_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
1053 SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL
, offsetof(ExecContext
, inaccessible_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
1054 SD_BUS_PROPERTY("ExecPaths", "as", NULL
, offsetof(ExecContext
, exec_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
1055 SD_BUS_PROPERTY("NoExecPaths", "as", NULL
, offsetof(ExecContext
, no_exec_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
1056 SD_BUS_PROPERTY("ExecSearchPath", "as", NULL
, offsetof(ExecContext
, exec_search_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
1057 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_propagation_flag
), SD_BUS_VTABLE_PROPERTY_CONST
),
1058 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1059 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
1060 SD_BUS_PROPERTY("ProtectClock", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_clock
), SD_BUS_VTABLE_PROPERTY_CONST
),
1061 SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_kernel_tunables
), SD_BUS_VTABLE_PROPERTY_CONST
),
1062 SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_kernel_modules
), SD_BUS_VTABLE_PROPERTY_CONST
),
1063 SD_BUS_PROPERTY("ProtectKernelLogs", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_kernel_logs
), SD_BUS_VTABLE_PROPERTY_CONST
),
1064 SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_control_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
1065 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
1066 SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool
, offsetof(ExecContext
, private_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
1067 SD_BUS_PROPERTY("PrivateMounts", "b", bus_property_get_tristate
, offsetof(ExecContext
, private_mounts
), SD_BUS_VTABLE_PROPERTY_CONST
),
1068 SD_BUS_PROPERTY("PrivateIPC", "b", bus_property_get_bool
, offsetof(ExecContext
, private_ipc
), SD_BUS_VTABLE_PROPERTY_CONST
),
1069 SD_BUS_PROPERTY("ProtectHome", "s", property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
1070 SD_BUS_PROPERTY("ProtectSystem", "s", property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
1071 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1072 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
1073 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
1074 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1075 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1076 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1077 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
1078 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
1079 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1080 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1081 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int
, offsetof(ExecContext
, syscall_errno
), SD_BUS_VTABLE_PROPERTY_CONST
),
1082 SD_BUS_PROPERTY("SystemCallLog", "(bas)", property_get_syscall_log
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1083 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, offsetof(ExecContext
, personality
), SD_BUS_VTABLE_PROPERTY_CONST
),
1084 SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool
, offsetof(ExecContext
, lock_personality
), SD_BUS_VTABLE_PROPERTY_CONST
),
1085 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1086 SD_BUS_PROPERTY("RuntimeDirectorySymlink", "a(sst)", bus_property_get_exec_dir_symlink
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_RUNTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1087 SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", bus_property_get_exec_preserve_mode
, offsetof(ExecContext
, runtime_directory_preserve_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
1088 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_RUNTIME
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
1089 SD_BUS_PROPERTY("RuntimeDirectory", "as", bus_property_get_exec_dir
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_RUNTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1090 SD_BUS_PROPERTY("StateDirectorySymlink", "a(sst)", bus_property_get_exec_dir_symlink
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_STATE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1091 SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_STATE
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
1092 SD_BUS_PROPERTY("StateDirectory", "as", bus_property_get_exec_dir
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_STATE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1093 SD_BUS_PROPERTY("CacheDirectorySymlink", "a(sst)", bus_property_get_exec_dir_symlink
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CACHE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1094 SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CACHE
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
1095 SD_BUS_PROPERTY("CacheDirectory", "as", bus_property_get_exec_dir
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CACHE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1096 SD_BUS_PROPERTY("LogsDirectorySymlink", "a(sst)", bus_property_get_exec_dir_symlink
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_LOGS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1097 SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_LOGS
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
1098 SD_BUS_PROPERTY("LogsDirectory", "as", bus_property_get_exec_dir
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_LOGS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1099 SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CONFIGURATION
].mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
1100 SD_BUS_PROPERTY("ConfigurationDirectory", "as", bus_property_get_exec_dir
, offsetof(ExecContext
, directories
[EXEC_DIRECTORY_CONFIGURATION
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1101 SD_BUS_PROPERTY("TimeoutCleanUSec", "t", bus_property_get_usec
, offsetof(ExecContext
, timeout_clean_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
1102 SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool
, offsetof(ExecContext
, memory_deny_write_execute
), SD_BUS_VTABLE_PROPERTY_CONST
),
1103 SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool
, offsetof(ExecContext
, restrict_realtime
), SD_BUS_VTABLE_PROPERTY_CONST
),
1104 SD_BUS_PROPERTY("RestrictSUIDSGID", "b", bus_property_get_bool
, offsetof(ExecContext
, restrict_suid_sgid
), SD_BUS_VTABLE_PROPERTY_CONST
),
1105 SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong
, offsetof(ExecContext
, restrict_namespaces
), SD_BUS_VTABLE_PROPERTY_CONST
),
1106 SD_BUS_PROPERTY("RestrictFileSystems", "(bas)", property_get_restrict_filesystems
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1107 SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1108 SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1109 SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1110 SD_BUS_PROPERTY("MountAPIVFS", "b", property_get_mount_apivfs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1111 SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode
, offsetof(ExecContext
, keyring_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
1112 SD_BUS_PROPERTY("ProtectProc", "s", property_get_protect_proc
, offsetof(ExecContext
, protect_proc
), SD_BUS_VTABLE_PROPERTY_CONST
),
1113 SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset
, offsetof(ExecContext
, proc_subset
), SD_BUS_VTABLE_PROPERTY_CONST
),
1114 SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool
, offsetof(ExecContext
, protect_hostname
), SD_BUS_VTABLE_PROPERTY_CONST
),
1115 SD_BUS_PROPERTY("MemoryKSM", "b", bus_property_get_tristate
, offsetof(ExecContext
, memory_ksm
), SD_BUS_VTABLE_PROPERTY_CONST
),
1116 SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL
, offsetof(ExecContext
, network_namespace_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
1117 SD_BUS_PROPERTY("IPCNamespacePath", "s", NULL
, offsetof(ExecContext
, ipc_namespace_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
1118 SD_BUS_PROPERTY("RootImagePolicy", "s", property_get_image_policy
, offsetof(ExecContext
, root_image_policy
), SD_BUS_VTABLE_PROPERTY_CONST
),
1119 SD_BUS_PROPERTY("MountImagePolicy", "s", property_get_image_policy
, offsetof(ExecContext
, mount_image_policy
), SD_BUS_VTABLE_PROPERTY_CONST
),
1120 SD_BUS_PROPERTY("ExtensionImagePolicy", "s", property_get_image_policy
, offsetof(ExecContext
, extension_image_policy
), SD_BUS_VTABLE_PROPERTY_CONST
),
1122 /* Obsolete/redundant properties: */
1123 SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string
, 0, SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
1124 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_paths
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
1125 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_paths
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
1126 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_paths
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
1127 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
1132 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
1141 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
1145 r
= sd_bus_message_append(reply
, "s", c
->path
);
1149 r
= sd_bus_message_append_strv(reply
, c
->argv
);
1153 r
= sd_bus_message_append(reply
, "bttttuii",
1154 !!(c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
),
1155 c
->exec_status
.start_timestamp
.realtime
,
1156 c
->exec_status
.start_timestamp
.monotonic
,
1157 c
->exec_status
.exit_timestamp
.realtime
,
1158 c
->exec_status
.exit_timestamp
.monotonic
,
1159 (uint32_t) c
->exec_status
.pid
,
1160 (int32_t) c
->exec_status
.code
,
1161 (int32_t) c
->exec_status
.status
);
1165 return sd_bus_message_close_container(reply
);
1168 static int append_exec_ex_command(sd_bus_message
*reply
, ExecCommand
*c
) {
1169 _cleanup_strv_free_
char **ex_opts
= NULL
;
1178 r
= sd_bus_message_open_container(reply
, 'r', "sasasttttuii");
1182 r
= sd_bus_message_append(reply
, "s", c
->path
);
1186 r
= sd_bus_message_append_strv(reply
, c
->argv
);
1190 r
= exec_command_flags_to_strv(c
->flags
, &ex_opts
);
1194 r
= sd_bus_message_append_strv(reply
, ex_opts
);
1198 r
= sd_bus_message_append(reply
, "ttttuii",
1199 c
->exec_status
.start_timestamp
.realtime
,
1200 c
->exec_status
.start_timestamp
.monotonic
,
1201 c
->exec_status
.exit_timestamp
.realtime
,
1202 c
->exec_status
.exit_timestamp
.monotonic
,
1203 (uint32_t) c
->exec_status
.pid
,
1204 (int32_t) c
->exec_status
.code
,
1205 (int32_t) c
->exec_status
.status
);
1209 return sd_bus_message_close_container(reply
);
1212 int bus_property_get_exec_command(
1215 const char *interface
,
1216 const char *property
,
1217 sd_bus_message
*reply
,
1219 sd_bus_error
*ret_error
) {
1221 ExecCommand
*c
= (ExecCommand
*) userdata
;
1227 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
1231 r
= append_exec_command(reply
, c
);
1235 return sd_bus_message_close_container(reply
);
1238 int bus_property_get_exec_command_list(
1241 const char *interface
,
1242 const char *property
,
1243 sd_bus_message
*reply
,
1245 sd_bus_error
*ret_error
) {
1247 ExecCommand
*exec_command
= *(ExecCommand
**) userdata
;
1253 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
1257 LIST_FOREACH(command
, c
, exec_command
) {
1258 r
= append_exec_command(reply
, c
);
1263 return sd_bus_message_close_container(reply
);
1266 int bus_property_get_exec_ex_command_list(
1269 const char *interface
,
1270 const char *property
,
1271 sd_bus_message
*reply
,
1273 sd_bus_error
*ret_error
) {
1275 ExecCommand
*exec_command
= *(ExecCommand
**) userdata
;
1281 r
= sd_bus_message_open_container(reply
, 'a', "(sasasttttuii)");
1285 LIST_FOREACH(command
, c
, exec_command
) {
1286 r
= append_exec_ex_command(reply
, c
);
1291 return sd_bus_message_close_container(reply
);
1294 static char *exec_command_flags_to_exec_chars(ExecCommandFlags flags
) {
1295 return strjoin(FLAGS_SET(flags
, EXEC_COMMAND_IGNORE_FAILURE
) ? "-" : "",
1296 FLAGS_SET(flags
, EXEC_COMMAND_NO_ENV_EXPAND
) ? ":" : "",
1297 FLAGS_SET(flags
, EXEC_COMMAND_FULLY_PRIVILEGED
) ? "+" : "",
1298 FLAGS_SET(flags
, EXEC_COMMAND_NO_SETUID
) ? "!" : "",
1299 FLAGS_SET(flags
, EXEC_COMMAND_AMBIENT_MAGIC
) ? "!!" : "");
1302 int bus_set_transient_exec_command(
1305 ExecCommand
**exec_command
,
1306 sd_bus_message
*message
,
1307 UnitWriteFlags flags
,
1308 sd_bus_error
*error
) {
1309 bool is_ex_prop
= endswith(name
, "Ex");
1313 /* Drop Ex from the written setting. E.g. ExecStart=, not ExecStartEx=. */
1314 const char *written_name
= is_ex_prop
? strndupa(name
, strlen(name
) - 2) : name
;
1316 r
= sd_bus_message_enter_container(message
, 'a', is_ex_prop
? "(sasas)" : "(sasb)");
1320 while ((r
= sd_bus_message_enter_container(message
, 'r', is_ex_prop
? "sasas" : "sasb")) > 0) {
1321 _cleanup_strv_free_
char **argv
= NULL
, **ex_opts
= NULL
;
1325 r
= sd_bus_message_read(message
, "s", &path
);
1329 if (!path_is_absolute(path
) && !filename_is_valid(path
))
1330 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
1331 "\"%s\" is neither a valid executable name nor an absolute path",
1334 r
= sd_bus_message_read_strv(message
, &argv
);
1338 if (strv_isempty(argv
))
1339 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
1340 "\"%s\" argv cannot be empty", name
);
1342 r
= is_ex_prop
? sd_bus_message_read_strv(message
, &ex_opts
) : sd_bus_message_read(message
, "b", &b
);
1346 r
= sd_bus_message_exit_container(message
);
1350 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1353 c
= new0(ExecCommand
, 1);
1357 c
->path
= strdup(path
);
1363 c
->argv
= TAKE_PTR(argv
);
1366 r
= exec_command_flags_from_strv(ex_opts
, &c
->flags
);
1370 c
->flags
= b
? EXEC_COMMAND_IGNORE_FAILURE
: 0;
1372 path_simplify(c
->path
);
1373 exec_command_append_list(exec_command
, c
);
1381 r
= sd_bus_message_exit_container(message
);
1385 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1386 _cleanup_(memstream_done
) MemStream m
= {};
1387 _cleanup_free_
char *buf
= NULL
;
1391 *exec_command
= exec_command_free_list(*exec_command
);
1393 f
= memstream_init(&m
);
1397 fprintf(f
, "%s=\n", written_name
);
1399 LIST_FOREACH(command
, c
, *exec_command
) {
1400 _cleanup_free_
char *a
= NULL
, *exec_chars
= NULL
;
1401 UnitWriteFlags esc_flags
= UNIT_ESCAPE_SPECIFIERS
|
1402 (FLAGS_SET(c
->flags
, EXEC_COMMAND_NO_ENV_EXPAND
) ? UNIT_ESCAPE_EXEC_SYNTAX
: UNIT_ESCAPE_EXEC_SYNTAX_ENV
);
1404 exec_chars
= exec_command_flags_to_exec_chars(c
->flags
);
1408 a
= unit_concat_strv(c
->argv
, esc_flags
);
1412 if (streq_ptr(c
->path
, c
->argv
? c
->argv
[0] : NULL
))
1413 fprintf(f
, "%s=%s%s\n", written_name
, exec_chars
, a
);
1415 _cleanup_free_
char *t
= NULL
;
1418 p
= unit_escape_setting(c
->path
, esc_flags
, &t
);
1422 fprintf(f
, "%s=%s@%s %s\n", written_name
, exec_chars
, p
, a
);
1426 r
= memstream_finalize(&m
, &buf
, NULL
);
1430 unit_write_setting(u
, flags
, written_name
, buf
);
1436 static int parse_personality(const char *s
, unsigned long *p
) {
1441 v
= personality_from_string(s
);
1442 if (v
== PERSONALITY_INVALID
)
1449 static const char* mount_propagation_flag_to_string_with_check(unsigned long n
) {
1450 if (!mount_propagation_flag_is_valid(n
))
1453 return mount_propagation_flag_to_string(n
);
1456 static BUS_DEFINE_SET_TRANSIENT(nsec
, "t", uint64_t, nsec_t
, NSEC_FMT
);
1457 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level
, "i", int32_t, int, "%" PRIi32
, log_level_is_valid
);
1459 static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno
, "i", int32_t, int, "%" PRIi32
, seccomp_errno_or_action_is_valid
);
1461 static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input
, ExecInput
, exec_input_from_string
);
1462 static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output
, ExecOutput
, exec_output_from_string
);
1463 static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode
, ExecUtmpMode
, exec_utmp_mode_from_string
);
1464 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system
, ProtectSystem
, protect_system_from_string
);
1465 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home
, ProtectHome
, protect_home_from_string
);
1466 static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode
, ExecKeyringMode
, exec_keyring_mode_from_string
);
1467 static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_proc
, ProtectProc
, protect_proc_from_string
);
1468 static BUS_DEFINE_SET_TRANSIENT_PARSE(proc_subset
, ProcSubset
, proc_subset_from_string
);
1469 BUS_DEFINE_SET_TRANSIENT_PARSE(exec_preserve_mode
, ExecPreserveMode
, exec_preserve_mode_from_string
);
1470 static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality
, unsigned long, parse_personality
);
1471 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits
, "i", int32_t, int, "%" PRIi32
, secure_bits_to_string_alloc_with_check
);
1472 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability
, "t", uint64_t, uint64_t, "%" PRIu64
, capability_set_to_string
);
1473 static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag
, "t", uint64_t, unsigned long, "%" PRIu64
, namespace_flags_to_string
);
1474 static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_propagation_flag
, "t", uint64_t, unsigned long, "%" PRIu64
, mount_propagation_flag_to_string_with_check
);
1476 int bus_exec_context_set_transient_property(
1480 sd_bus_message
*message
,
1481 UnitWriteFlags flags
,
1482 sd_bus_error
*error
) {
1492 flags
|= UNIT_PRIVATE
;
1494 if (streq(name
, "User"))
1495 return bus_set_transient_user_relaxed(u
, name
, &c
->user
, message
, flags
, error
);
1497 if (streq(name
, "Group"))
1498 return bus_set_transient_user_relaxed(u
, name
, &c
->group
, message
, flags
, error
);
1500 if (streq(name
, "SetLoginEnvironment"))
1501 return bus_set_transient_tristate(u
, name
, &c
->set_login_environment
, message
, flags
, error
);
1503 if (streq(name
, "TTYPath"))
1504 return bus_set_transient_path(u
, name
, &c
->tty_path
, message
, flags
, error
);
1506 if (streq(name
, "RootImage"))
1507 return bus_set_transient_path(u
, name
, &c
->root_image
, message
, flags
, error
);
1509 if (streq(name
, "RootImageOptions")) {
1510 _cleanup_(mount_options_free_allp
) MountOptions
*options
= NULL
;
1511 _cleanup_free_
char *format_str
= NULL
;
1513 r
= bus_read_mount_options(message
, error
, &options
, &format_str
, " ");
1517 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1519 LIST_JOIN(mount_options
, c
->root_image_options
, options
);
1520 unit_write_settingf(
1521 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
,
1526 c
->root_image_options
= mount_options_free_all(c
->root_image_options
);
1527 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1534 if (streq(name
, "RootHash")) {
1535 const void *roothash_decoded
;
1536 size_t roothash_decoded_size
;
1538 r
= sd_bus_message_read_array(message
, 'y', &roothash_decoded
, &roothash_decoded_size
);
1542 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1543 _cleanup_free_
char *encoded
= NULL
;
1545 if (roothash_decoded_size
== 0) {
1546 c
->root_hash_path
= mfree(c
->root_hash_path
);
1547 c
->root_hash
= mfree(c
->root_hash
);
1548 c
->root_hash_size
= 0;
1550 unit_write_settingf(u
, flags
, name
, "RootHash=");
1552 _cleanup_free_
void *p
= NULL
;
1554 encoded
= hexmem(roothash_decoded
, roothash_decoded_size
);
1558 p
= memdup(roothash_decoded
, roothash_decoded_size
);
1562 free_and_replace(c
->root_hash
, p
);
1563 c
->root_hash_size
= roothash_decoded_size
;
1564 c
->root_hash_path
= mfree(c
->root_hash_path
);
1566 unit_write_settingf(u
, flags
, name
, "RootHash=%s", encoded
);
1573 if (streq(name
, "RootHashPath")) {
1574 c
->root_hash_size
= 0;
1575 c
->root_hash
= mfree(c
->root_hash
);
1577 return bus_set_transient_path(u
, "RootHash", &c
->root_hash_path
, message
, flags
, error
);
1580 if (streq(name
, "RootHashSignature")) {
1581 const void *roothash_sig_decoded
;
1582 size_t roothash_sig_decoded_size
;
1584 r
= sd_bus_message_read_array(message
, 'y', &roothash_sig_decoded
, &roothash_sig_decoded_size
);
1588 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1589 _cleanup_free_
char *encoded
= NULL
;
1591 if (roothash_sig_decoded_size
== 0) {
1592 c
->root_hash_sig_path
= mfree(c
->root_hash_sig_path
);
1593 c
->root_hash_sig
= mfree(c
->root_hash_sig
);
1594 c
->root_hash_sig_size
= 0;
1596 unit_write_settingf(u
, flags
, name
, "RootHashSignature=");
1598 _cleanup_free_
void *p
= NULL
;
1601 len
= base64mem(roothash_sig_decoded
, roothash_sig_decoded_size
, &encoded
);
1605 p
= memdup(roothash_sig_decoded
, roothash_sig_decoded_size
);
1609 free_and_replace(c
->root_hash_sig
, p
);
1610 c
->root_hash_sig_size
= roothash_sig_decoded_size
;
1611 c
->root_hash_sig_path
= mfree(c
->root_hash_sig_path
);
1613 unit_write_settingf(u
, flags
, name
, "RootHashSignature=base64:%s", encoded
);
1620 if (streq(name
, "RootHashSignaturePath")) {
1621 c
->root_hash_sig_size
= 0;
1622 c
->root_hash_sig
= mfree(c
->root_hash_sig
);
1624 return bus_set_transient_path(u
, "RootHashSignature", &c
->root_hash_sig_path
, message
, flags
, error
);
1627 if (streq(name
, "RootVerity"))
1628 return bus_set_transient_path(u
, name
, &c
->root_verity
, message
, flags
, error
);
1630 if (streq(name
, "RootDirectory"))
1631 return bus_set_transient_path(u
, name
, &c
->root_directory
, message
, flags
, error
);
1633 if (streq(name
, "RootEphemeral"))
1634 return bus_set_transient_bool(u
, name
, &c
->root_ephemeral
, message
, flags
, error
);
1636 if (streq(name
, "SyslogIdentifier"))
1637 return bus_set_transient_string(u
, name
, &c
->syslog_identifier
, message
, flags
, error
);
1639 if (streq(name
, "LogLevelMax"))
1640 return bus_set_transient_log_level(u
, name
, &c
->log_level_max
, message
, flags
, error
);
1642 if (streq(name
, "LogRateLimitIntervalUSec"))
1643 return bus_set_transient_usec(u
, name
, &c
->log_ratelimit_interval_usec
, message
, flags
, error
);
1645 if (streq(name
, "LogRateLimitBurst"))
1646 return bus_set_transient_unsigned(u
, name
, &c
->log_ratelimit_burst
, message
, flags
, error
);
1648 if (streq(name
, "LogFilterPatterns")) {
1649 /* Use _cleanup_free_, not _cleanup_strv_free_, as we don't want the content of the strv
1651 _cleanup_free_
char **allow_list
= NULL
, **deny_list
= NULL
;
1652 const char *pattern
;
1655 r
= sd_bus_message_enter_container(message
, 'a', "(bs)");
1659 while ((r
= sd_bus_message_read(message
, "(bs)", &is_allowlist
, &pattern
)) > 0) {
1660 _cleanup_(pattern_freep
) pcre2_code
*compiled_pattern
= NULL
;
1662 if (isempty(pattern
))
1665 r
= pattern_compile_and_log(pattern
, 0, &compiled_pattern
);
1669 r
= strv_push(is_allowlist
? &allow_list
: &deny_list
, (char *)pattern
);
1676 r
= sd_bus_message_exit_container(message
);
1680 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1681 if (strv_isempty(allow_list
) && strv_isempty(deny_list
)) {
1682 c
->log_filter_allowed_patterns
= set_free_free(c
->log_filter_allowed_patterns
);
1683 c
->log_filter_denied_patterns
= set_free_free(c
->log_filter_denied_patterns
);
1684 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1686 r
= set_put_strdupv(&c
->log_filter_allowed_patterns
, allow_list
);
1689 r
= set_put_strdupv(&c
->log_filter_denied_patterns
, deny_list
);
1693 STRV_FOREACH(unit_pattern
, allow_list
)
1694 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, *unit_pattern
);
1695 STRV_FOREACH(unit_pattern
, deny_list
)
1696 unit_write_settingf(u
, flags
, name
, "%s=~%s", name
, *unit_pattern
);
1703 if (streq(name
, "Personality"))
1704 return bus_set_transient_personality(u
, name
, &c
->personality
, message
, flags
, error
);
1706 if (streq(name
, "StandardInput"))
1707 return bus_set_transient_std_input(u
, name
, &c
->std_input
, message
, flags
, error
);
1709 if (streq(name
, "StandardOutput"))
1710 return bus_set_transient_std_output(u
, name
, &c
->std_output
, message
, flags
, error
);
1712 if (streq(name
, "StandardError"))
1713 return bus_set_transient_std_output(u
, name
, &c
->std_error
, message
, flags
, error
);
1715 if (streq(name
, "IgnoreSIGPIPE"))
1716 return bus_set_transient_bool(u
, name
, &c
->ignore_sigpipe
, message
, flags
, error
);
1718 if (streq(name
, "TTYVHangup"))
1719 return bus_set_transient_bool(u
, name
, &c
->tty_vhangup
, message
, flags
, error
);
1721 if (streq(name
, "TTYReset"))
1722 return bus_set_transient_bool(u
, name
, &c
->tty_reset
, message
, flags
, error
);
1724 if (streq(name
, "TTYVTDisallocate"))
1725 return bus_set_transient_bool(u
, name
, &c
->tty_vt_disallocate
, message
, flags
, error
);
1727 if (streq(name
, "TTYRows"))
1728 return bus_set_transient_unsigned(u
, name
, &c
->tty_rows
, message
, flags
, error
);
1730 if (streq(name
, "TTYColumns"))
1731 return bus_set_transient_unsigned(u
, name
, &c
->tty_cols
, message
, flags
, error
);
1733 if (streq(name
, "PrivateTmp"))
1734 return bus_set_transient_bool(u
, name
, &c
->private_tmp
, message
, flags
, error
);
1736 if (streq(name
, "PrivateDevices"))
1737 return bus_set_transient_bool(u
, name
, &c
->private_devices
, message
, flags
, error
);
1739 if (streq(name
, "PrivateMounts"))
1740 return bus_set_transient_tristate(u
, name
, &c
->private_mounts
, message
, flags
, error
);
1742 if (streq(name
, "PrivateNetwork"))
1743 return bus_set_transient_bool(u
, name
, &c
->private_network
, message
, flags
, error
);
1745 if (streq(name
, "PrivateIPC"))
1746 return bus_set_transient_bool(u
, name
, &c
->private_ipc
, message
, flags
, error
);
1748 if (streq(name
, "PrivateUsers"))
1749 return bus_set_transient_bool(u
, name
, &c
->private_users
, message
, flags
, error
);
1751 if (streq(name
, "NoNewPrivileges"))
1752 return bus_set_transient_bool(u
, name
, &c
->no_new_privileges
, message
, flags
, error
);
1754 if (streq(name
, "SyslogLevelPrefix"))
1755 return bus_set_transient_bool(u
, name
, &c
->syslog_level_prefix
, message
, flags
, error
);
1757 if (streq(name
, "MemoryDenyWriteExecute"))
1758 return bus_set_transient_bool(u
, name
, &c
->memory_deny_write_execute
, message
, flags
, error
);
1760 if (streq(name
, "RestrictRealtime"))
1761 return bus_set_transient_bool(u
, name
, &c
->restrict_realtime
, message
, flags
, error
);
1763 if (streq(name
, "RestrictSUIDSGID"))
1764 return bus_set_transient_bool(u
, name
, &c
->restrict_suid_sgid
, message
, flags
, error
);
1766 if (streq(name
, "DynamicUser"))
1767 return bus_set_transient_bool(u
, name
, &c
->dynamic_user
, message
, flags
, error
);
1769 if (streq(name
, "RemoveIPC"))
1770 return bus_set_transient_bool(u
, name
, &c
->remove_ipc
, message
, flags
, error
);
1772 if (streq(name
, "ProtectKernelTunables"))
1773 return bus_set_transient_bool(u
, name
, &c
->protect_kernel_tunables
, message
, flags
, error
);
1775 if (streq(name
, "ProtectKernelModules"))
1776 return bus_set_transient_bool(u
, name
, &c
->protect_kernel_modules
, message
, flags
, error
);
1778 if (streq(name
, "ProtectKernelLogs"))
1779 return bus_set_transient_bool(u
, name
, &c
->protect_kernel_logs
, message
, flags
, error
);
1781 if (streq(name
, "ProtectClock"))
1782 return bus_set_transient_bool(u
, name
, &c
->protect_clock
, message
, flags
, error
);
1784 if (streq(name
, "ProtectControlGroups"))
1785 return bus_set_transient_bool(u
, name
, &c
->protect_control_groups
, message
, flags
, error
);
1787 if (streq(name
, "CPUSchedulingResetOnFork"))
1788 return bus_set_transient_bool(u
, name
, &c
->cpu_sched_reset_on_fork
, message
, flags
, error
);
1790 if (streq(name
, "NonBlocking"))
1791 return bus_set_transient_bool(u
, name
, &c
->non_blocking
, message
, flags
, error
);
1793 if (streq(name
, "LockPersonality"))
1794 return bus_set_transient_bool(u
, name
, &c
->lock_personality
, message
, flags
, error
);
1796 if (streq(name
, "ProtectHostname"))
1797 return bus_set_transient_bool(u
, name
, &c
->protect_hostname
, message
, flags
, error
);
1799 if (streq(name
, "MemoryKSM"))
1800 return bus_set_transient_tristate(u
, name
, &c
->memory_ksm
, message
, flags
, error
);
1802 if (streq(name
, "UtmpIdentifier"))
1803 return bus_set_transient_string(u
, name
, &c
->utmp_id
, message
, flags
, error
);
1805 if (streq(name
, "UtmpMode"))
1806 return bus_set_transient_utmp_mode(u
, name
, &c
->utmp_mode
, message
, flags
, error
);
1808 if (streq(name
, "PAMName"))
1809 return bus_set_transient_string(u
, name
, &c
->pam_name
, message
, flags
, error
);
1811 if (streq(name
, "TimerSlackNSec"))
1812 return bus_set_transient_nsec(u
, name
, &c
->timer_slack_nsec
, message
, flags
, error
);
1814 if (streq(name
, "ProtectSystem"))
1815 return bus_set_transient_protect_system(u
, name
, &c
->protect_system
, message
, flags
, error
);
1817 if (streq(name
, "ProtectHome"))
1818 return bus_set_transient_protect_home(u
, name
, &c
->protect_home
, message
, flags
, error
);
1820 if (streq(name
, "KeyringMode"))
1821 return bus_set_transient_keyring_mode(u
, name
, &c
->keyring_mode
, message
, flags
, error
);
1823 if (streq(name
, "ProtectProc"))
1824 return bus_set_transient_protect_proc(u
, name
, &c
->protect_proc
, message
, flags
, error
);
1826 if (streq(name
, "ProcSubset"))
1827 return bus_set_transient_proc_subset(u
, name
, &c
->proc_subset
, message
, flags
, error
);
1829 if (streq(name
, "RuntimeDirectoryPreserve"))
1830 return bus_set_transient_exec_preserve_mode(u
, name
, &c
->runtime_directory_preserve_mode
, message
, flags
, error
);
1832 if (streq(name
, "UMask"))
1833 return bus_set_transient_mode_t(u
, name
, &c
->umask
, message
, flags
, error
);
1835 if (streq(name
, "RuntimeDirectoryMode"))
1836 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_RUNTIME
].mode
, message
, flags
, error
);
1838 if (streq(name
, "StateDirectoryMode"))
1839 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_STATE
].mode
, message
, flags
, error
);
1841 if (streq(name
, "CacheDirectoryMode"))
1842 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_CACHE
].mode
, message
, flags
, error
);
1844 if (streq(name
, "LogsDirectoryMode"))
1845 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_LOGS
].mode
, message
, flags
, error
);
1847 if (streq(name
, "ConfigurationDirectoryMode"))
1848 return bus_set_transient_mode_t(u
, name
, &c
->directories
[EXEC_DIRECTORY_CONFIGURATION
].mode
, message
, flags
, error
);
1850 if (streq(name
, "SELinuxContext"))
1851 return bus_set_transient_string(u
, name
, &c
->selinux_context
, message
, flags
, error
);
1853 if (streq(name
, "SecureBits"))
1854 return bus_set_transient_secure_bits(u
, name
, &c
->secure_bits
, message
, flags
, error
);
1856 if (streq(name
, "CapabilityBoundingSet"))
1857 return bus_set_transient_capability(u
, name
, &c
->capability_bounding_set
, message
, flags
, error
);
1859 if (streq(name
, "AmbientCapabilities"))
1860 return bus_set_transient_capability(u
, name
, &c
->capability_ambient_set
, message
, flags
, error
);
1862 if (streq(name
, "RestrictNamespaces"))
1863 return bus_set_transient_namespace_flag(u
, name
, &c
->restrict_namespaces
, message
, flags
, error
);
1865 if (streq(name
, "RestrictFileSystems")) {
1867 _cleanup_strv_free_
char **l
= NULL
;
1869 r
= sd_bus_message_enter_container(message
, 'r', "bas");
1873 r
= sd_bus_message_read(message
, "b", &allow_list
);
1877 r
= sd_bus_message_read_strv(message
, &l
);
1881 r
= sd_bus_message_exit_container(message
);
1885 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1886 _cleanup_free_
char *joined
= NULL
;
1887 FilesystemParseFlags invert_flag
= allow_list
? 0 : FILESYSTEM_PARSE_INVERT
;
1889 if (strv_isempty(l
)) {
1890 c
->restrict_filesystems_allow_list
= false;
1891 c
->restrict_filesystems
= set_free_free(c
->restrict_filesystems
);
1893 unit_write_setting(u
, flags
, name
, "RestrictFileSystems=");
1897 if (!c
->restrict_filesystems
)
1898 c
->restrict_filesystems_allow_list
= allow_list
;
1900 STRV_FOREACH(s
, l
) {
1901 r
= lsm_bpf_parse_filesystem(
1903 &c
->restrict_filesystems
,
1904 FILESYSTEM_PARSE_LOG
|
1905 (invert_flag
? FILESYSTEM_PARSE_INVERT
: 0)|
1906 (c
->restrict_filesystems_allow_list
? FILESYSTEM_PARSE_ALLOW_LIST
: 0),
1912 joined
= strv_join(l
, " ");
1916 unit_write_settingf(u
, flags
, name
, "%s=%s%s", name
, allow_list
? "" : "~", joined
);
1922 if (streq(name
, "MountFlags"))
1923 return bus_set_transient_mount_propagation_flag(u
, name
, &c
->mount_propagation_flag
, message
, flags
, error
);
1925 if (streq(name
, "NetworkNamespacePath"))
1926 return bus_set_transient_path(u
, name
, &c
->network_namespace_path
, message
, flags
, error
);
1928 if (streq(name
, "IPCNamespacePath"))
1929 return bus_set_transient_path(u
, name
, &c
->ipc_namespace_path
, message
, flags
, error
);
1931 if (streq(name
, "SupplementaryGroups")) {
1932 _cleanup_strv_free_
char **l
= NULL
;
1934 r
= sd_bus_message_read_strv(message
, &l
);
1939 if (!isempty(*p
) && !valid_user_group_name(*p
, VALID_USER_ALLOW_NUMERIC
|VALID_USER_RELAX
|VALID_USER_WARN
))
1940 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
1941 "Invalid supplementary group names");
1943 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1944 if (strv_isempty(l
)) {
1945 c
->supplementary_groups
= strv_free(c
->supplementary_groups
);
1946 unit_write_settingf(u
, flags
, name
, "%s=", name
);
1948 _cleanup_free_
char *joined
= NULL
;
1950 r
= strv_extend_strv(&c
->supplementary_groups
, l
, true);
1954 joined
= strv_join(c
->supplementary_groups
, " ");
1958 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s", name
, joined
);
1964 } else if (STR_IN_SET(name
, "SetCredential", "SetCredentialEncrypted")) {
1965 bool isempty
= true;
1967 r
= sd_bus_message_enter_container(message
, 'a', "(say)");
1976 r
= sd_bus_message_enter_container(message
, 'r', "say");
1982 r
= sd_bus_message_read(message
, "s", &id
);
1986 r
= sd_bus_message_read_array(message
, 'y', &p
, &sz
);
1990 r
= sd_bus_message_exit_container(message
);
1994 if (!credential_name_valid(id
))
1995 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Credential ID is invalid: %s", id
);
1999 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2000 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
2001 _cleanup_free_
void *copy
= NULL
;
2002 ExecSetCredential
*old
;
2004 copy
= memdup(p
, sz
);
2008 old
= hashmap_get(c
->set_credentials
, id
);
2010 free_and_replace(old
->data
, copy
);
2012 old
->encrypted
= streq(name
, "SetCredentialEncrypted");
2014 _cleanup_(exec_set_credential_freep
) ExecSetCredential
*sc
= NULL
;
2016 sc
= new(ExecSetCredential
, 1);
2020 *sc
= (ExecSetCredential
) {
2022 .data
= TAKE_PTR(copy
),
2024 .encrypted
= streq(name
, "SetCredentialEncrypted"),
2030 r
= hashmap_ensure_put(&c
->set_credentials
, &exec_set_credential_hash_ops
, sc
->id
, sc
);
2037 a
= specifier_escape(id
);
2041 b
= cescape_length(p
, sz
);
2045 (void) unit_write_settingf(u
, flags
, name
, "%s=%s:%s", name
, a
, b
);
2049 r
= sd_bus_message_exit_container(message
);
2053 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && isempty
) {
2054 c
->set_credentials
= hashmap_free(c
->set_credentials
);
2055 (void) unit_write_settingf(u
, flags
, name
, "%s=", name
);
2060 } else if (STR_IN_SET(name
, "LoadCredential", "LoadCredentialEncrypted")) {
2061 bool isempty
= true;
2063 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
2068 const char *id
, *source
;
2070 r
= sd_bus_message_read(message
, "(ss)", &id
, &source
);
2076 if (!credential_name_valid(id
))
2077 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Credential ID is invalid: %s", id
);
2079 if (!(path_is_absolute(source
) ? path_is_normalized(source
) : credential_name_valid(source
)))
2080 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Credential source is invalid: %s", source
);
2084 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2085 bool encrypted
= streq(name
, "LoadCredentialEncrypted");
2087 r
= hashmap_put_credential(&c
->load_credentials
, id
, source
, encrypted
);
2091 (void) unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s:%s", name
, id
, source
);
2095 r
= sd_bus_message_exit_container(message
);
2099 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && isempty
) {
2100 c
->load_credentials
= hashmap_free(c
->load_credentials
);
2101 (void) unit_write_settingf(u
, flags
, name
, "%s=", name
);
2106 } else if (streq(name
, "ImportCredential")) {
2107 bool isempty
= true;
2109 r
= sd_bus_message_enter_container(message
, 'a', "s");
2116 r
= sd_bus_message_read(message
, "s", &s
);
2122 if (!credential_glob_valid(s
))
2123 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Credential name or glob is invalid: %s", s
);
2127 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2128 r
= set_put_strdup(&c
->import_credentials
, s
);
2132 (void) unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s", name
, s
);
2136 r
= sd_bus_message_exit_container(message
);
2140 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && isempty
) {
2141 c
->import_credentials
= set_free_free(c
->import_credentials
);
2142 (void) unit_write_settingf(u
, flags
, name
, "%s=", name
);
2147 } else if (streq(name
, "SyslogLevel")) {
2150 r
= sd_bus_message_read(message
, "i", &level
);
2154 if (!log_level_is_valid(level
))
2155 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log level value out of range");
2157 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2158 c
->syslog_priority
= (c
->syslog_priority
& LOG_FACMASK
) | level
;
2159 unit_write_settingf(u
, flags
, name
, "SyslogLevel=%i", level
);
2164 } else if (streq(name
, "SyslogFacility")) {
2167 r
= sd_bus_message_read(message
, "i", &facility
);
2171 if (!log_facility_unshifted_is_valid(facility
))
2172 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log facility value out of range");
2174 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2175 c
->syslog_priority
= (facility
<< 3) | LOG_PRI(c
->syslog_priority
);
2176 unit_write_settingf(u
, flags
, name
, "SyslogFacility=%i", facility
);
2181 } else if (streq(name
, "LogNamespace")) {
2184 r
= sd_bus_message_read(message
, "s", &n
);
2188 if (!isempty(n
) && !log_namespace_name_valid(n
))
2189 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log namespace name not valid");
2191 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2194 c
->log_namespace
= mfree(c
->log_namespace
);
2195 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2197 r
= free_and_strdup(&c
->log_namespace
, n
);
2201 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, n
);
2207 } else if (streq(name
, "LogExtraFields")) {
2210 r
= sd_bus_message_enter_container(message
, 'a', "ay");
2215 _cleanup_free_
void *copy
= NULL
;
2221 /* Note that we expect a byte array for each field, instead of a string. That's because on the
2222 * lower-level journal fields can actually contain binary data and are not restricted to text,
2223 * and we should not "lose precision" in our types on the way. That said, I am pretty sure
2224 * actually encoding binary data as unit metadata is not a good idea. Hence we actually refuse
2225 * any actual binary data, and only accept UTF-8. This allows us to eventually lift this
2226 * limitation, should a good, valid use case arise. */
2228 r
= sd_bus_message_read_array(message
, 'y', &p
, &sz
);
2234 if (memchr(p
, 0, sz
))
2235 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field contains zero byte");
2237 eq
= memchr(p
, '=', sz
);
2239 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field contains no '=' character");
2240 if (!journal_field_valid(p
, eq
- (const char*) p
, false))
2241 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field invalid");
2243 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2244 t
= reallocarray(c
->log_extra_fields
, c
->n_log_extra_fields
+1, sizeof(struct iovec
));
2247 c
->log_extra_fields
= t
;
2250 copy
= malloc(sz
+ 1);
2254 memcpy(copy
, p
, sz
);
2255 ((uint8_t*) copy
)[sz
] = 0;
2257 if (!utf8_is_valid(copy
))
2258 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Journal field is not valid UTF-8");
2260 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2261 c
->log_extra_fields
[c
->n_log_extra_fields
++] = IOVEC_MAKE(copy
, sz
);
2262 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
, name
, "LogExtraFields=%s", (char*) copy
);
2270 r
= sd_bus_message_exit_container(message
);
2274 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && n
== 0) {
2275 exec_context_free_log_extra_fields(c
);
2276 unit_write_setting(u
, flags
, name
, "LogExtraFields=");
2284 if (streq(name
, "SystemCallErrorNumber"))
2285 return bus_set_transient_errno(u
, name
, &c
->syscall_errno
, message
, flags
, error
);
2287 if (streq(name
, "SystemCallFilter")) {
2289 _cleanup_strv_free_
char **l
= NULL
;
2291 r
= sd_bus_message_enter_container(message
, 'r', "bas");
2295 r
= sd_bus_message_read(message
, "b", &allow_list
);
2299 r
= sd_bus_message_read_strv(message
, &l
);
2303 r
= sd_bus_message_exit_container(message
);
2307 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2308 _cleanup_free_
char *joined
= NULL
;
2309 SeccompParseFlags invert_flag
= allow_list
? 0 : SECCOMP_PARSE_INVERT
;
2311 if (strv_isempty(l
)) {
2312 c
->syscall_allow_list
= false;
2313 c
->syscall_filter
= hashmap_free(c
->syscall_filter
);
2315 unit_write_settingf(u
, flags
, name
, "SystemCallFilter=");
2319 if (!c
->syscall_filter
) {
2320 c
->syscall_filter
= hashmap_new(NULL
);
2321 if (!c
->syscall_filter
)
2324 c
->syscall_allow_list
= allow_list
;
2326 if (c
->syscall_allow_list
) {
2327 r
= seccomp_parse_syscall_filter("@default",
2330 SECCOMP_PARSE_PERMISSIVE
|
2331 SECCOMP_PARSE_ALLOW_LIST
,
2339 STRV_FOREACH(s
, l
) {
2340 _cleanup_free_
char *n
= NULL
;
2343 r
= parse_syscall_and_errno(*s
, &n
, &e
);
2347 if (allow_list
&& e
>= 0)
2350 r
= seccomp_parse_syscall_filter(n
,
2353 SECCOMP_PARSE_LOG
| SECCOMP_PARSE_PERMISSIVE
|
2355 (c
->syscall_allow_list
? SECCOMP_PARSE_ALLOW_LIST
: 0),
2362 joined
= strv_join(l
, " ");
2366 unit_write_settingf(u
, flags
, name
, "SystemCallFilter=%s%s", allow_list
? "" : "~", joined
);
2371 } else if (streq(name
, "SystemCallLog")) {
2373 _cleanup_strv_free_
char **l
= NULL
;
2375 r
= sd_bus_message_enter_container(message
, 'r', "bas");
2379 r
= sd_bus_message_read(message
, "b", &allow_list
);
2383 r
= sd_bus_message_read_strv(message
, &l
);
2387 r
= sd_bus_message_exit_container(message
);
2391 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2392 _cleanup_free_
char *joined
= NULL
;
2393 SeccompParseFlags invert_flag
= allow_list
? 0 : SECCOMP_PARSE_INVERT
;
2395 if (strv_isempty(l
)) {
2396 c
->syscall_log_allow_list
= false;
2397 c
->syscall_log
= hashmap_free(c
->syscall_log
);
2399 unit_write_settingf(u
, flags
, name
, "SystemCallLog=");
2403 if (!c
->syscall_log
) {
2404 c
->syscall_log
= hashmap_new(NULL
);
2405 if (!c
->syscall_log
)
2408 c
->syscall_log_allow_list
= allow_list
;
2411 STRV_FOREACH(s
, l
) {
2412 r
= seccomp_parse_syscall_filter(*s
,
2413 -1, /* errno not used */
2415 SECCOMP_PARSE_LOG
| SECCOMP_PARSE_PERMISSIVE
|
2417 (c
->syscall_log_allow_list
? SECCOMP_PARSE_ALLOW_LIST
: 0),
2424 joined
= strv_join(l
, " ");
2428 unit_write_settingf(u
, flags
, name
, "SystemCallLog=%s%s", allow_list
? "" : "~", joined
);
2433 } else if (streq(name
, "SystemCallArchitectures")) {
2434 _cleanup_strv_free_
char **l
= NULL
;
2436 r
= sd_bus_message_read_strv(message
, &l
);
2440 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2441 _cleanup_free_
char *joined
= NULL
;
2443 if (strv_isempty(l
))
2444 c
->syscall_archs
= set_free(c
->syscall_archs
);
2446 STRV_FOREACH(s
, l
) {
2449 r
= seccomp_arch_from_string(*s
, &a
);
2453 r
= set_ensure_put(&c
->syscall_archs
, NULL
, UINT32_TO_PTR(a
+ 1));
2458 joined
= strv_join(l
, " ");
2462 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
2467 } else if (streq(name
, "RestrictAddressFamilies")) {
2468 _cleanup_strv_free_
char **l
= NULL
;
2471 r
= sd_bus_message_enter_container(message
, 'r', "bas");
2475 r
= sd_bus_message_read(message
, "b", &allow_list
);
2479 r
= sd_bus_message_read_strv(message
, &l
);
2483 r
= sd_bus_message_exit_container(message
);
2487 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2488 _cleanup_free_
char *joined
= NULL
;
2490 if (strv_isempty(l
)) {
2491 c
->address_families_allow_list
= allow_list
;
2492 c
->address_families
= set_free(c
->address_families
);
2494 unit_write_settingf(u
, flags
, name
, "RestrictAddressFamilies=%s",
2495 allow_list
? "none" : "");
2499 if (!c
->address_families
) {
2500 c
->address_families
= set_new(NULL
);
2501 if (!c
->address_families
)
2504 c
->address_families_allow_list
= allow_list
;
2507 STRV_FOREACH(s
, l
) {
2510 af
= af_from_name(*s
);
2514 if (allow_list
== c
->address_families_allow_list
) {
2515 r
= set_put(c
->address_families
, INT_TO_PTR(af
));
2519 set_remove(c
->address_families
, INT_TO_PTR(af
));
2522 joined
= strv_join(l
, " ");
2526 unit_write_settingf(u
, flags
, name
, "RestrictAddressFamilies=%s%s", allow_list
? "" : "~", joined
);
2532 if (STR_IN_SET(name
, "CPUAffinity", "NUMAMask")) {
2535 bool affinity
= streq(name
, "CPUAffinity");
2536 _cleanup_(cpu_set_reset
) CPUSet set
= {};
2538 r
= sd_bus_message_read_array(message
, 'y', &a
, &n
);
2542 r
= cpu_set_from_dbus(a
, n
, &set
);
2546 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2548 cpu_set_reset(affinity
? &c
->cpu_set
: &c
->numa_policy
.nodes
);
2549 unit_write_settingf(u
, flags
, name
, "%s=", name
);
2551 _cleanup_free_
char *str
= NULL
;
2553 str
= cpu_set_to_string(&set
);
2557 /* We forego any optimizations here, and always create the structure using
2558 * cpu_set_add_all(), because we don't want to care if the existing size we
2559 * got over dbus is appropriate. */
2560 r
= cpu_set_add_all(affinity
? &c
->cpu_set
: &c
->numa_policy
.nodes
, &set
);
2564 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, str
);
2570 } else if (streq(name
, "CPUAffinityFromNUMA")) {
2573 r
= sd_bus_message_read_basic(message
, 'b', &q
);
2577 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2578 c
->cpu_affinity_from_numa
= q
;
2579 unit_write_settingf(u
, flags
, name
, "%s=%s", "CPUAffinity", "numa");
2584 } else if (streq(name
, "NUMAPolicy")) {
2587 r
= sd_bus_message_read(message
, "i", &type
);
2591 if (!mpol_is_valid(type
))
2592 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid NUMAPolicy value: %i", type
);
2594 if (!UNIT_WRITE_FLAGS_NOOP(flags
))
2595 c
->numa_policy
.type
= type
;
2599 } else if (streq(name
, "Nice")) {
2602 r
= sd_bus_message_read(message
, "i", &q
);
2606 if (!nice_is_valid(q
))
2607 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid Nice value: %i", q
);
2609 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2613 unit_write_settingf(u
, flags
, name
, "Nice=%i", q
);
2618 } else if (streq(name
, "CPUSchedulingPolicy")) {
2621 r
= sd_bus_message_read(message
, "i", &q
);
2625 if (!sched_policy_is_valid(q
))
2626 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid CPU scheduling policy: %i", q
);
2628 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2629 _cleanup_free_
char *s
= NULL
;
2631 r
= sched_policy_to_string_alloc(q
, &s
);
2635 c
->cpu_sched_policy
= q
;
2636 c
->cpu_sched_priority
= CLAMP(c
->cpu_sched_priority
, sched_get_priority_min(q
), sched_get_priority_max(q
));
2637 c
->cpu_sched_set
= true;
2639 unit_write_settingf(u
, flags
, name
, "CPUSchedulingPolicy=%s", s
);
2644 } else if (streq(name
, "CPUSchedulingPriority")) {
2647 r
= sd_bus_message_read(message
, "i", &p
);
2651 /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0. Policy might be set
2652 * later so we do not check the precise range, but only the generic outer bounds. */
2653 if (p
< 0 || p
> 99)
2654 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid CPU scheduling priority: %i", p
);
2656 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2657 c
->cpu_sched_priority
= p
;
2658 c
->cpu_sched_set
= true;
2660 unit_write_settingf(u
, flags
, name
, "CPUSchedulingPriority=%i", p
);
2665 } else if (streq(name
, "IOSchedulingClass")) {
2668 r
= sd_bus_message_read(message
, "i", &q
);
2672 if (!ioprio_class_is_valid(q
))
2673 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid IO scheduling class: %i", q
);
2675 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2676 _cleanup_free_
char *s
= NULL
;
2678 r
= ioprio_class_to_string_alloc(q
, &s
);
2682 c
->ioprio
= ioprio_normalize(ioprio_prio_value(q
, ioprio_prio_data(c
->ioprio
)));
2683 c
->ioprio_set
= true;
2685 unit_write_settingf(u
, flags
, name
, "IOSchedulingClass=%s", s
);
2690 } else if (streq(name
, "IOSchedulingPriority")) {
2693 r
= sd_bus_message_read(message
, "i", &p
);
2697 if (!ioprio_priority_is_valid(p
))
2698 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid IO scheduling priority: %i", p
);
2700 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2701 c
->ioprio
= ioprio_normalize(ioprio_prio_value(ioprio_prio_class(c
->ioprio
), p
));
2702 c
->ioprio_set
= true;
2704 unit_write_settingf(u
, flags
, name
, "IOSchedulingPriority=%i", p
);
2709 } else if (streq(name
, "MountAPIVFS")) {
2712 r
= bus_set_transient_bool(u
, name
, &b
, message
, flags
, error
);
2716 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2717 c
->mount_apivfs
= b
;
2718 c
->mount_apivfs_set
= true;
2723 } else if (streq(name
, "WorkingDirectory")) {
2727 r
= sd_bus_message_read(message
, "s", &s
);
2737 if (!isempty(s
) && !streq(s
, "~") && !path_is_absolute(s
))
2738 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
2740 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2741 if (streq(s
, "~")) {
2742 c
->working_directory
= mfree(c
->working_directory
);
2743 c
->working_directory_home
= true;
2745 r
= free_and_strdup(&c
->working_directory
, empty_to_null(s
));
2749 c
->working_directory_home
= false;
2752 c
->working_directory_missing_ok
= missing_ok
;
2753 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
2758 } else if (STR_IN_SET(name
,
2759 "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
2762 r
= sd_bus_message_read(message
, "s", &s
);
2766 if (!isempty(s
) && !fdname_is_valid(s
))
2767 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid file descriptor name");
2769 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2771 if (streq(name
, "StandardInputFileDescriptorName")) {
2772 r
= free_and_strdup(c
->stdio_fdname
+ STDIN_FILENO
, empty_to_null(s
));
2776 c
->std_input
= EXEC_INPUT_NAMED_FD
;
2777 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardInput=fd:%s", exec_context_fdname(c
, STDIN_FILENO
));
2779 } else if (streq(name
, "StandardOutputFileDescriptorName")) {
2780 r
= free_and_strdup(c
->stdio_fdname
+ STDOUT_FILENO
, empty_to_null(s
));
2784 c
->std_output
= EXEC_OUTPUT_NAMED_FD
;
2785 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardOutput=fd:%s", exec_context_fdname(c
, STDOUT_FILENO
));
2788 assert(streq(name
, "StandardErrorFileDescriptorName"));
2790 r
= free_and_strdup(&c
->stdio_fdname
[STDERR_FILENO
], empty_to_null(s
));
2794 c
->std_error
= EXEC_OUTPUT_NAMED_FD
;
2795 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardError=fd:%s", exec_context_fdname(c
, STDERR_FILENO
));
2801 } else if (STR_IN_SET(name
,
2802 "StandardInputFile",
2803 "StandardOutputFile", "StandardOutputFileToAppend", "StandardOutputFileToTruncate",
2804 "StandardErrorFile", "StandardErrorFileToAppend", "StandardErrorFileToTruncate")) {
2807 r
= sd_bus_message_read(message
, "s", &s
);
2812 if (!path_is_absolute(s
))
2813 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not absolute", s
);
2814 if (!path_is_normalized(s
))
2815 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not normalized", s
);
2818 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2820 if (streq(name
, "StandardInputFile")) {
2821 r
= free_and_strdup(&c
->stdio_file
[STDIN_FILENO
], empty_to_null(s
));
2825 c
->std_input
= EXEC_INPUT_FILE
;
2826 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardInput=file:%s", s
);
2828 } else if (STR_IN_SET(name
, "StandardOutputFile", "StandardOutputFileToAppend", "StandardOutputFileToTruncate")) {
2829 r
= free_and_strdup(&c
->stdio_file
[STDOUT_FILENO
], empty_to_null(s
));
2833 if (streq(name
, "StandardOutputFile")) {
2834 c
->std_output
= EXEC_OUTPUT_FILE
;
2835 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardOutput=file:%s", s
);
2836 } else if (streq(name
, "StandardOutputFileToAppend")) {
2837 c
->std_output
= EXEC_OUTPUT_FILE_APPEND
;
2838 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardOutput=append:%s", s
);
2840 assert(streq(name
, "StandardOutputFileToTruncate"));
2841 c
->std_output
= EXEC_OUTPUT_FILE_TRUNCATE
;
2842 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardOutput=truncate:%s", s
);
2845 assert(STR_IN_SET(name
, "StandardErrorFile", "StandardErrorFileToAppend", "StandardErrorFileToTruncate"));
2847 r
= free_and_strdup(&c
->stdio_file
[STDERR_FILENO
], empty_to_null(s
));
2851 if (streq(name
, "StandardErrorFile")) {
2852 c
->std_error
= EXEC_OUTPUT_FILE
;
2853 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardError=file:%s", s
);
2854 } else if (streq(name
, "StandardErrorFileToAppend")) {
2855 c
->std_error
= EXEC_OUTPUT_FILE_APPEND
;
2856 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardError=append:%s", s
);
2858 assert(streq(name
, "StandardErrorFileToTruncate"));
2859 c
->std_error
= EXEC_OUTPUT_FILE_TRUNCATE
;
2860 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "StandardError=truncate:%s", s
);
2867 } else if (streq(name
, "StandardInputData")) {
2871 r
= sd_bus_message_read_array(message
, 'y', &p
, &sz
);
2875 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2876 _cleanup_free_
char *encoded
= NULL
;
2879 c
->stdin_data
= mfree(c
->stdin_data
);
2880 c
->stdin_data_size
= 0;
2882 unit_write_settingf(u
, flags
, name
, "StandardInputData=");
2887 if (c
->stdin_data_size
+ sz
< c
->stdin_data_size
|| /* check for overflow */
2888 c
->stdin_data_size
+ sz
> EXEC_STDIN_DATA_MAX
)
2891 n
= base64mem(p
, sz
, &encoded
);
2895 q
= realloc(c
->stdin_data
, c
->stdin_data_size
+ sz
);
2899 memcpy((uint8_t*) q
+ c
->stdin_data_size
, p
, sz
);
2902 c
->stdin_data_size
+= sz
;
2904 unit_write_settingf(u
, flags
, name
, "StandardInputData=%s", encoded
);
2910 } else if (streq(name
, "Environment")) {
2912 _cleanup_strv_free_
char **l
= NULL
;
2914 r
= sd_bus_message_read_strv(message
, &l
);
2918 if (!strv_env_is_valid(l
))
2919 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
2921 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2922 if (strv_isempty(l
)) {
2923 c
->environment
= strv_free(c
->environment
);
2924 unit_write_setting(u
, flags
, name
, "Environment=");
2926 _cleanup_free_
char *joined
= NULL
;
2929 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
);
2933 e
= strv_env_merge(c
->environment
, l
);
2937 strv_free_and_replace(c
->environment
, e
);
2938 unit_write_settingf(u
, flags
, name
, "Environment=%s", joined
);
2944 } else if (streq(name
, "UnsetEnvironment")) {
2946 _cleanup_strv_free_
char **l
= NULL
;
2948 r
= sd_bus_message_read_strv(message
, &l
);
2952 if (!strv_env_name_or_assignment_is_valid(l
))
2953 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid UnsetEnvironment= list.");
2955 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2956 if (strv_isempty(l
)) {
2957 c
->unset_environment
= strv_free(c
->unset_environment
);
2958 unit_write_setting(u
, flags
, name
, "UnsetEnvironment=");
2960 _cleanup_free_
char *joined
= NULL
;
2963 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
|UNIT_ESCAPE_C
);
2967 e
= strv_env_merge(c
->unset_environment
, l
);
2971 strv_free_and_replace(c
->unset_environment
, e
);
2972 unit_write_settingf(u
, flags
, name
, "UnsetEnvironment=%s", joined
);
2978 } else if (streq(name
, "OOMScoreAdjust")) {
2981 r
= sd_bus_message_read(message
, "i", &oa
);
2985 if (!oom_score_adjust_is_valid(oa
))
2986 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "OOM score adjust value out of range");
2988 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
2989 c
->oom_score_adjust
= oa
;
2990 c
->oom_score_adjust_set
= true;
2991 unit_write_settingf(u
, flags
, name
, "OOMScoreAdjust=%i", oa
);
2996 } else if (streq(name
, "CoredumpFilter")) {
2999 r
= sd_bus_message_read(message
, "t", &f
);
3003 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3004 c
->coredump_filter
= f
;
3005 c
->coredump_filter_set
= true;
3006 unit_write_settingf(u
, flags
, name
, "CoredumpFilter=0x%"PRIx64
, f
);
3011 } else if (streq(name
, "EnvironmentFiles")) {
3012 _cleanup_(memstream_done
) MemStream m
= {};
3013 _cleanup_free_
char *joined
= NULL
;
3014 _cleanup_strv_free_
char **l
= NULL
;
3017 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
3021 f
= memstream_init(&m
);
3025 fputs("EnvironmentFile=\n", f
);
3027 STRV_FOREACH(i
, c
->environment_files
) {
3028 _cleanup_free_
char *q
= NULL
;
3030 q
= specifier_escape(*i
);
3034 fprintf(f
, "EnvironmentFile=%s\n", q
);
3037 while ((r
= sd_bus_message_enter_container(message
, 'r', "sb")) > 0) {
3041 r
= sd_bus_message_read(message
, "sb", &path
, &b
);
3045 r
= sd_bus_message_exit_container(message
);
3049 if (!path_is_absolute(path
))
3050 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not absolute.", path
);
3052 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3053 _cleanup_free_
char *q
= NULL
, *buf
= NULL
;
3055 buf
= strjoin(b
? "-" : "", path
);
3059 q
= specifier_escape(buf
);
3063 fprintf(f
, "EnvironmentFile=%s\n", q
);
3065 r
= strv_consume(&l
, TAKE_PTR(buf
));
3073 r
= sd_bus_message_exit_container(message
);
3077 r
= memstream_finalize(&m
, &joined
, NULL
);
3081 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3082 if (strv_isempty(l
)) {
3083 c
->environment_files
= strv_free(c
->environment_files
);
3084 unit_write_setting(u
, flags
, name
, "EnvironmentFile=");
3086 r
= strv_extend_strv(&c
->environment_files
, l
, true);
3090 unit_write_setting(u
, flags
, name
, joined
);
3096 } else if (streq(name
, "PassEnvironment")) {
3098 _cleanup_strv_free_
char **l
= NULL
;
3100 r
= sd_bus_message_read_strv(message
, &l
);
3104 if (!strv_env_name_is_valid(l
))
3105 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid PassEnvironment= block.");
3107 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3108 if (strv_isempty(l
)) {
3109 c
->pass_environment
= strv_free(c
->pass_environment
);
3110 unit_write_setting(u
, flags
, name
, "PassEnvironment=");
3112 _cleanup_free_
char *joined
= NULL
;
3114 r
= strv_extend_strv(&c
->pass_environment
, l
, true);
3118 /* We write just the new settings out to file, with unresolved specifiers. */
3119 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
3123 unit_write_settingf(u
, flags
, name
, "PassEnvironment=%s", joined
);
3129 } else if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories",
3130 "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths", "ExecPaths", "NoExecPaths",
3131 "ExtensionDirectories")) {
3132 _cleanup_strv_free_
char **l
= NULL
;
3135 r
= sd_bus_message_read_strv(message
, &l
);
3139 STRV_FOREACH(p
, l
) {
3143 offset
= i
[0] == '-';
3144 offset
+= i
[offset
] == '+';
3145 if (!path_is_absolute(i
+ offset
))
3146 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
3148 path_simplify(i
+ offset
);
3151 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3152 if (STR_IN_SET(name
, "ReadWriteDirectories", "ReadWritePaths"))
3153 dirs
= &c
->read_write_paths
;
3154 else if (STR_IN_SET(name
, "ReadOnlyDirectories", "ReadOnlyPaths"))
3155 dirs
= &c
->read_only_paths
;
3156 else if (streq(name
, "ExecPaths"))
3157 dirs
= &c
->exec_paths
;
3158 else if (streq(name
, "NoExecPaths"))
3159 dirs
= &c
->no_exec_paths
;
3160 else if (streq(name
, "ExtensionDirectories"))
3161 dirs
= &c
->extension_directories
;
3162 else /* "InaccessiblePaths" */
3163 dirs
= &c
->inaccessible_paths
;
3165 if (strv_isempty(l
)) {
3166 *dirs
= strv_free(*dirs
);
3167 unit_write_settingf(u
, flags
, name
, "%s=", name
);
3169 _cleanup_free_
char *joined
= NULL
;
3171 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
3175 r
= strv_extend_strv(dirs
, l
, true);
3179 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
3185 } else if (streq(name
, "ExecSearchPath")) {
3186 _cleanup_strv_free_
char **l
= NULL
;
3188 r
= sd_bus_message_read_strv(message
, &l
);
3193 if (!path_is_absolute(*p
) || !path_is_normalized(*p
) || strchr(*p
, ':'))
3194 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid %s", name
);
3196 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3197 if (strv_isempty(l
)) {
3198 c
->exec_search_path
= strv_free(c
->exec_search_path
);
3199 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "ExecSearchPath=");
3201 _cleanup_free_
char *joined
= NULL
;
3202 r
= strv_extend_strv(&c
->exec_search_path
, l
, true);
3205 joined
= strv_join(c
->exec_search_path
, ":");
3208 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "ExecSearchPath=%s", joined
);
3214 } else if (STR_IN_SET(name
, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
3215 _cleanup_strv_free_
char **l
= NULL
;
3217 r
= sd_bus_message_read_strv(message
, &l
);
3221 STRV_FOREACH(p
, l
) {
3222 if (!path_is_normalized(*p
))
3223 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= path is not normalized: %s", name
, *p
);
3225 if (path_is_absolute(*p
))
3226 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= path is absolute: %s", name
, *p
);
3228 if (path_startswith(*p
, "private"))
3229 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= path can't be 'private': %s", name
, *p
);
3232 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3233 ExecDirectoryType i
;
3236 assert_se((i
= exec_directory_type_from_string(name
)) >= 0);
3237 d
= c
->directories
+ i
;
3239 if (strv_isempty(l
)) {
3240 exec_directory_done(d
);
3241 unit_write_settingf(u
, flags
, name
, "%s=", name
);
3243 _cleanup_free_
char *joined
= NULL
;
3245 STRV_FOREACH(source
, l
) {
3246 r
= exec_directory_add(d
, *source
, NULL
);
3250 exec_directory_sort(d
);
3252 joined
= unit_concat_strv(l
, UNIT_ESCAPE_SPECIFIERS
);
3256 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, joined
);
3262 } else if (STR_IN_SET(name
, "AppArmorProfile", "SmackProcessLabel")) {
3266 r
= sd_bus_message_read(message
, "(bs)", &ignore
, &s
);
3270 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3274 if (streq(name
, "AppArmorProfile")) {
3275 p
= &c
->apparmor_profile
;
3276 b
= &c
->apparmor_profile_ignore
;
3277 } else { /* "SmackProcessLabel" */
3278 p
= &c
->smack_process_label
;
3279 b
= &c
->smack_process_label_ignore
;
3286 if (free_and_strdup(p
, s
) < 0)
3291 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "%s=%s%s", name
, ignore
? "-" : "", strempty(s
));
3296 } else if (STR_IN_SET(name
, "BindPaths", "BindReadOnlyPaths")) {
3297 char *source
, *destination
;
3299 uint64_t mount_flags
;
3302 r
= sd_bus_message_enter_container(message
, 'a', "(ssbt)");
3306 while ((r
= sd_bus_message_read(message
, "(ssbt)", &source
, &destination
, &ignore_enoent
, &mount_flags
)) > 0) {
3308 if (!path_is_absolute(source
))
3309 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is not absolute.", source
);
3310 if (!path_is_absolute(destination
))
3311 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Destination path %s is not absolute.", destination
);
3312 if (!IN_SET(mount_flags
, 0, MS_REC
))
3313 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown mount flags.");
3315 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3316 r
= bind_mount_add(&c
->bind_mounts
, &c
->n_bind_mounts
,
3319 .destination
= destination
,
3320 .read_only
= !!strstr(name
, "ReadOnly"),
3321 .recursive
= !!(mount_flags
& MS_REC
),
3322 .ignore_enoent
= ignore_enoent
,
3327 unit_write_settingf(
3328 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
,
3331 ignore_enoent
? "-" : "",
3334 (mount_flags
& MS_REC
) ? "rbind" : "norbind");
3342 r
= sd_bus_message_exit_container(message
);
3347 bind_mount_free_many(c
->bind_mounts
, c
->n_bind_mounts
);
3348 c
->bind_mounts
= NULL
;
3349 c
->n_bind_mounts
= 0;
3351 unit_write_settingf(u
, flags
, name
, "%s=", name
);
3356 } else if (streq(name
, "TemporaryFileSystem")) {
3357 const char *path
, *options
;
3360 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
3364 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &options
)) > 0) {
3366 if (!path_is_absolute(path
))
3367 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Mount point %s is not absolute.", path
);
3369 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3370 r
= temporary_filesystem_add(&c
->temporary_filesystems
, &c
->n_temporary_filesystems
, path
, options
);
3374 unit_write_settingf(
3375 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
,
3387 r
= sd_bus_message_exit_container(message
);
3392 temporary_filesystem_free_many(c
->temporary_filesystems
, c
->n_temporary_filesystems
);
3393 c
->temporary_filesystems
= NULL
;
3394 c
->n_temporary_filesystems
= 0;
3396 unit_write_settingf(u
, flags
, name
, "%s=", name
);
3401 } else if ((suffix
= startswith(name
, "Limit"))) {
3402 const char *soft
= NULL
;
3405 ri
= rlimit_from_string(suffix
);
3407 soft
= endswith(suffix
, "Soft");
3411 n
= strndupa_safe(suffix
, soft
- suffix
);
3412 ri
= rlimit_from_string(n
);
3414 name
= strjoina("Limit", n
);
3422 r
= sd_bus_message_read(message
, "t", &rl
);
3426 if (rl
== UINT64_MAX
)
3431 if ((uint64_t) x
!= rl
)
3435 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3436 _cleanup_free_
char *f
= NULL
;
3439 if (c
->rlimit
[ri
]) {
3440 nl
= *c
->rlimit
[ri
];
3447 /* When the resource limit is not initialized yet, then assign the value to both fields */
3448 nl
= (struct rlimit
) {
3453 r
= rlimit_format(&nl
, &f
);
3458 *c
->rlimit
[ri
] = nl
;
3460 c
->rlimit
[ri
] = newdup(struct rlimit
, &nl
, 1);
3465 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, f
);
3471 } else if (streq(name
, "MountImages")) {
3472 _cleanup_free_
char *format_str
= NULL
;
3473 MountImage
*mount_images
= NULL
;
3474 size_t n_mount_images
= 0;
3475 char *source
, *destination
;
3478 r
= sd_bus_message_enter_container(message
, 'a', "(ssba(ss))");
3483 _cleanup_(mount_options_free_allp
) MountOptions
*options
= NULL
;
3484 _cleanup_free_
char *source_escaped
= NULL
, *destination_escaped
= NULL
;
3487 r
= sd_bus_message_enter_container(message
, 'r', "ssba(ss)");
3491 r
= sd_bus_message_read(message
, "ssb", &source
, &destination
, &permissive
);
3495 if (!path_is_absolute(source
))
3496 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is not absolute.", source
);
3497 if (!path_is_normalized(source
))
3498 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is not normalized.", source
);
3499 if (!path_is_absolute(destination
))
3500 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Destination path %s is not absolute.", destination
);
3501 if (!path_is_normalized(destination
))
3502 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Destination path %s is not normalized.", destination
);
3504 /* Need to store them in the unit with the escapes, so that they can be parsed again */
3505 source_escaped
= shell_escape(source
, ":");
3506 if (!source_escaped
)
3508 destination_escaped
= shell_escape(destination
, ":");
3509 if (!destination_escaped
)
3512 tuple
= strjoin(format_str
,
3513 format_str
? " " : "",
3514 permissive
? "-" : "",
3517 destination_escaped
);
3520 free_and_replace(format_str
, tuple
);
3522 r
= bus_read_mount_options(message
, error
, &options
, &format_str
, ":");
3526 r
= sd_bus_message_exit_container(message
);
3530 r
= mount_image_add(&mount_images
, &n_mount_images
,
3533 .destination
= destination
,
3534 .mount_options
= options
,
3535 .ignore_enoent
= permissive
,
3536 .type
= MOUNT_IMAGE_DISCRETE
,
3544 r
= sd_bus_message_exit_container(message
);
3548 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3549 if (n_mount_images
== 0) {
3550 c
->mount_images
= mount_image_free_many(c
->mount_images
, &c
->n_mount_images
);
3552 unit_write_settingf(u
, flags
, name
, "%s=", name
);
3554 for (size_t i
= 0; i
< n_mount_images
; ++i
) {
3555 r
= mount_image_add(&c
->mount_images
, &c
->n_mount_images
, &mount_images
[i
]);
3560 unit_write_settingf(u
, flags
|UNIT_ESCAPE_C
|UNIT_ESCAPE_SPECIFIERS
,
3568 mount_images
= mount_image_free_many(mount_images
, &n_mount_images
);
3571 } else if (streq(name
, "ExtensionImages")) {
3572 _cleanup_free_
char *format_str
= NULL
;
3573 MountImage
*extension_images
= NULL
;
3574 size_t n_extension_images
= 0;
3576 r
= sd_bus_message_enter_container(message
, 'a', "(sba(ss))");
3581 _cleanup_(mount_options_free_allp
) MountOptions
*options
= NULL
;
3582 _cleanup_free_
char *source_escaped
= NULL
;
3583 char *source
, *tuple
;
3586 r
= sd_bus_message_enter_container(message
, 'r', "sba(ss)");
3590 r
= sd_bus_message_read(message
, "sb", &source
, &permissive
);
3594 if (!path_is_absolute(source
))
3595 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is not absolute.", source
);
3596 if (!path_is_normalized(source
))
3597 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is not normalized.", source
);
3599 /* Need to store them in the unit with the escapes, so that they can be parsed again */
3600 source_escaped
= shell_escape(source
, ":");
3601 if (!source_escaped
)
3604 tuple
= strjoin(format_str
,
3605 format_str
? " " : "",
3606 permissive
? "-" : "",
3610 free_and_replace(format_str
, tuple
);
3612 r
= bus_read_mount_options(message
, error
, &options
, &format_str
, ":");
3616 r
= sd_bus_message_exit_container(message
);
3620 r
= mount_image_add(&extension_images
, &n_extension_images
,
3623 .mount_options
= options
,
3624 .ignore_enoent
= permissive
,
3625 .type
= MOUNT_IMAGE_EXTENSION
,
3633 r
= sd_bus_message_exit_container(message
);
3637 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3638 if (n_extension_images
== 0) {
3639 c
->extension_images
= mount_image_free_many(c
->extension_images
, &c
->n_extension_images
);
3641 unit_write_settingf(u
, flags
, name
, "%s=", name
);
3643 for (size_t i
= 0; i
< n_extension_images
; ++i
) {
3644 r
= mount_image_add(&c
->extension_images
, &c
->n_extension_images
, &extension_images
[i
]);
3649 unit_write_settingf(u
, flags
|UNIT_ESCAPE_C
|UNIT_ESCAPE_SPECIFIERS
,
3657 extension_images
= mount_image_free_many(extension_images
, &n_extension_images
);
3661 } else if (STR_IN_SET(name
, "StateDirectorySymlink", "RuntimeDirectorySymlink", "CacheDirectorySymlink", "LogsDirectorySymlink")) {
3662 char *source
, *destination
;
3663 ExecDirectory
*directory
;
3664 uint64_t symlink_flags
; /* No flags for now, reserved for future uses. */
3665 ExecDirectoryType i
;
3667 assert_se((i
= exec_directory_type_symlink_from_string(name
)) >= 0);
3668 directory
= c
->directories
+ i
;
3670 r
= sd_bus_message_enter_container(message
, 'a', "(sst)");
3674 while ((r
= sd_bus_message_read(message
, "(sst)", &source
, &destination
, &symlink_flags
)) > 0) {
3675 if (!path_is_valid(source
))
3676 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is not valid.", source
);
3677 if (path_is_absolute(source
))
3678 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is absolute.", source
);
3679 if (!path_is_normalized(source
))
3680 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Source path %s is not normalized.", source
);
3681 if (!path_is_valid(destination
))
3682 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Destination path %s is not valid.", destination
);
3683 if (path_is_absolute(destination
))
3684 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Destination path %s is absolute.", destination
);
3685 if (!path_is_normalized(destination
))
3686 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Destination path %s is not normalized.", destination
);
3687 if (symlink_flags
!= 0)
3688 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Flags must be zero.");
3690 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3691 _cleanup_free_
char *destination_escaped
= NULL
, *source_escaped
= NULL
;
3693 r
= exec_directory_add(directory
, source
, destination
);
3697 /* Need to store them in the unit with the escapes, so that they can be parsed again */
3698 source_escaped
= xescape(source
, ":");
3699 destination_escaped
= xescape(destination
, ":");
3700 if (!source_escaped
|| !destination_escaped
)
3703 unit_write_settingf(
3704 u
, flags
|UNIT_ESCAPE_SPECIFIERS
, exec_directory_type_to_string(i
),
3706 exec_directory_type_to_string(i
),
3708 destination_escaped
);
3714 exec_directory_sort(directory
);
3716 r
= sd_bus_message_exit_container(message
);
3722 } else if (STR_IN_SET(name
, "RootImagePolicy", "MountImagePolicy", "ExtensionImagePolicy")) {
3723 _cleanup_(image_policy_freep
) ImagePolicy
*p
= NULL
;
3726 r
= sd_bus_message_read(message
, "s", &s
);
3730 r
= image_policy_from_string(s
, &p
);
3732 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Failed to parse image policy string: %s", s
);
3734 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
3735 _cleanup_free_
char *t
= NULL
;
3737 streq(name
, "RootImagePolicy") ? &c
->root_image_policy
:
3738 streq(name
, "MountImagePolicy") ? &c
->mount_image_policy
:
3739 &c
->extension_image_policy
;
3741 r
= image_policy_to_string(p
, /* simplify= */ true, &t
);
3745 image_policy_free(*pp
);
3748 unit_write_settingf(
3752 t
); /* no escaping necessary */