1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include <sys/personality.h>
11 #include <sys/types.h>
16 #include <linux/fs.h> /* Must be included after <sys/mount.h> */
18 #include "sd-messages.h"
21 #include "alloc-util.h"
24 #include "capability-util.h"
25 #include "cgroup-setup.h"
26 #include "constants.h"
27 #include "cpu-set-util.h"
28 #include "dev-setup.h"
31 #include "errno-list.h"
33 #include "exec-credential.h"
35 #include "execute-serialize.h"
36 #include "exit-status.h"
39 #include "format-util.h"
40 #include "glob-util.h"
41 #include "hexdecoct.h"
42 #include "ioprio-util.h"
43 #include "lock-util.h"
47 #include "manager-dump.h"
48 #include "memory-util.h"
49 #include "missing_fs.h"
50 #include "missing_prctl.h"
51 #include "mkdir-label.h"
52 #include "namespace.h"
53 #include "parse-util.h"
54 #include "path-util.h"
55 #include "process-util.h"
56 #include "rlimit-util.h"
58 #include "seccomp-util.h"
59 #include "securebits-util.h"
60 #include "selinux-util.h"
61 #include "serialize.h"
62 #include "sort-util.h"
64 #include "stat-util.h"
65 #include "string-table.h"
66 #include "string-util.h"
68 #include "syslog-util.h"
69 #include "terminal-util.h"
70 #include "tmpfile-util.h"
71 #include "umask-util.h"
72 #include "unit-serialize.h"
73 #include "user-util.h"
74 #include "utmp-wtmp.h"
76 static bool is_terminal_input(ExecInput i
) {
83 static bool is_terminal_output(ExecOutput o
) {
86 EXEC_OUTPUT_KMSG_AND_CONSOLE
,
87 EXEC_OUTPUT_JOURNAL_AND_CONSOLE
);
90 const char *exec_context_tty_path(const ExecContext
*context
) {
93 if (context
->stdio_as_fds
)
96 if (context
->tty_path
)
97 return context
->tty_path
;
99 return "/dev/console";
102 static void exec_context_determine_tty_size(
103 const ExecContext
*context
,
104 const char *tty_path
,
106 unsigned *ret_cols
) {
115 tty_path
= exec_context_tty_path(context
);
117 rows
= context
->tty_rows
;
118 cols
= context
->tty_cols
;
120 if (tty_path
&& (rows
== UINT_MAX
|| cols
== UINT_MAX
))
121 (void) proc_cmdline_tty_size(
123 rows
== UINT_MAX
? &rows
: NULL
,
124 cols
== UINT_MAX
? &cols
: NULL
);
130 int exec_context_apply_tty_size(
131 const ExecContext
*context
,
133 const char *tty_path
) {
137 exec_context_determine_tty_size(context
, tty_path
, &rows
, &cols
);
139 return terminal_set_size_fd(tty_fd
, tty_path
, rows
, cols
);
142 void exec_context_tty_reset(const ExecContext
*context
, const ExecParameters
*p
) {
143 _cleanup_close_
int _fd
= -EBADF
, lock_fd
= -EBADF
;
148 const char *path
= exec_context_tty_path(context
);
150 if (p
&& p
->stdin_fd
>= 0 && isatty(p
->stdin_fd
))
152 else if (path
&& (context
->tty_path
|| is_terminal_input(context
->std_input
) ||
153 is_terminal_output(context
->std_output
) || is_terminal_output(context
->std_error
))) {
154 fd
= _fd
= open_terminal(path
, O_RDWR
|O_NOCTTY
|O_CLOEXEC
|O_NONBLOCK
);
156 return (void) log_debug_errno(fd
, "Failed to open terminal '%s', ignoring: %m", path
);
158 return; /* nothing to do */
160 /* Take a synchronization lock for the duration of the setup that we do here.
161 * systemd-vconsole-setup.service also takes the lock to avoid being interrupted. We open a new fd
162 * that will be closed automatically, and operate on it for convenience. */
163 lock_fd
= lock_dev_console();
165 return (void) log_debug_errno(lock_fd
,
166 "Failed to lock /dev/console: %m");
168 if (context
->tty_vhangup
)
169 (void) terminal_vhangup_fd(fd
);
171 if (context
->tty_reset
)
172 (void) reset_terminal_fd(fd
, /* switch_to_text= */ true);
174 (void) exec_context_apply_tty_size(context
, fd
, path
);
176 if (context
->tty_vt_disallocate
&& path
)
177 (void) vt_disallocate(path
);
180 bool exec_needs_network_namespace(const ExecContext
*context
) {
183 return context
->private_network
|| context
->network_namespace_path
;
186 static bool exec_needs_ephemeral(const ExecContext
*context
) {
187 return (context
->root_image
|| context
->root_directory
) && context
->root_ephemeral
;
190 bool exec_needs_ipc_namespace(const ExecContext
*context
) {
193 return context
->private_ipc
|| context
->ipc_namespace_path
;
196 bool exec_needs_mount_namespace(
197 const ExecContext
*context
,
198 const ExecParameters
*params
,
199 const ExecRuntime
*runtime
) {
203 if (context
->root_image
)
206 if (!strv_isempty(context
->read_write_paths
) ||
207 !strv_isempty(context
->read_only_paths
) ||
208 !strv_isempty(context
->inaccessible_paths
) ||
209 !strv_isempty(context
->exec_paths
) ||
210 !strv_isempty(context
->no_exec_paths
))
213 if (context
->n_bind_mounts
> 0)
216 if (context
->n_temporary_filesystems
> 0)
219 if (context
->n_mount_images
> 0)
222 if (context
->n_extension_images
> 0)
225 if (!strv_isempty(context
->extension_directories
))
228 if (!IN_SET(context
->mount_propagation_flag
, 0, MS_SHARED
))
231 if (context
->private_tmp
&& runtime
&& runtime
->shared
&& (runtime
->shared
->tmp_dir
|| runtime
->shared
->var_tmp_dir
))
234 if (context
->private_devices
||
235 context
->private_mounts
> 0 ||
236 (context
->private_mounts
< 0 && exec_needs_network_namespace(context
)) ||
237 context
->protect_system
!= PROTECT_SYSTEM_NO
||
238 context
->protect_home
!= PROTECT_HOME_NO
||
239 context
->protect_kernel_tunables
||
240 context
->protect_kernel_modules
||
241 context
->protect_kernel_logs
||
242 context
->protect_control_groups
||
243 context
->protect_proc
!= PROTECT_PROC_DEFAULT
||
244 context
->proc_subset
!= PROC_SUBSET_ALL
||
245 exec_needs_ipc_namespace(context
))
248 if (context
->root_directory
) {
249 if (exec_context_get_effective_mount_apivfs(context
))
252 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++) {
253 if (params
&& !params
->prefix
[t
])
256 if (context
->directories
[t
].n_items
> 0)
261 if (context
->dynamic_user
&&
262 (context
->directories
[EXEC_DIRECTORY_STATE
].n_items
> 0 ||
263 context
->directories
[EXEC_DIRECTORY_CACHE
].n_items
> 0 ||
264 context
->directories
[EXEC_DIRECTORY_LOGS
].n_items
> 0))
267 if (context
->log_namespace
)
273 bool exec_directory_is_private(const ExecContext
*context
, ExecDirectoryType type
) {
276 if (!context
->dynamic_user
)
279 if (type
== EXEC_DIRECTORY_CONFIGURATION
)
282 if (type
== EXEC_DIRECTORY_RUNTIME
&& context
->runtime_directory_preserve_mode
== EXEC_PRESERVE_NO
)
288 int exec_params_get_cgroup_path(
289 const ExecParameters
*params
,
290 const CGroupContext
*c
,
293 const char *subgroup
= NULL
;
299 if (!params
->cgroup_path
)
302 /* If we are called for a unit where cgroup delegation is on, and the payload created its own populated
303 * subcgroup (which we expect it to do, after all it asked for delegation), then we cannot place the control
304 * processes started after the main unit's process in the unit's main cgroup because it is now an inner one,
305 * and inner cgroups may not contain processes. Hence, if delegation is on, and this is a control process,
306 * let's use ".control" as subcgroup instead. Note that we do so only for ExecStartPost=, ExecReload=,
307 * ExecStop=, ExecStopPost=, i.e. for the commands where the main process is already forked. For ExecStartPre=
308 * this is not necessary, the cgroup is still empty. We distinguish these cases with the EXEC_CONTROL_CGROUP
309 * flag, which is only passed for the former statements, not for the latter. */
311 if (FLAGS_SET(params
->flags
, EXEC_CGROUP_DELEGATE
) && (FLAGS_SET(params
->flags
, EXEC_CONTROL_CGROUP
) || c
->delegate_subgroup
)) {
312 if (FLAGS_SET(params
->flags
, EXEC_IS_CONTROL
))
313 subgroup
= ".control";
315 subgroup
= c
->delegate_subgroup
;
319 p
= path_join(params
->cgroup_path
, subgroup
);
321 p
= strdup(params
->cgroup_path
);
329 bool exec_context_get_cpu_affinity_from_numa(const ExecContext
*c
) {
332 return c
->cpu_affinity_from_numa
;
335 static void log_command_line(Unit
*unit
, const char *msg
, const char *executable
, char **argv
) {
343 _cleanup_free_
char *cmdline
= quote_command_line(argv
, SHELL_ESCAPE_EMPTY
);
345 log_unit_struct(unit
, LOG_DEBUG
,
346 "EXECUTABLE=%s", executable
,
347 LOG_UNIT_MESSAGE(unit
, "%s: %s", msg
, strnull(cmdline
)),
348 LOG_UNIT_INVOCATION_ID(unit
));
351 static int exec_context_load_environment(const Unit
*unit
, const ExecContext
*c
, char ***l
);
353 int exec_spawn(Unit
*unit
,
354 ExecCommand
*command
,
355 const ExecContext
*context
,
356 ExecParameters
*params
,
357 ExecRuntime
*runtime
,
358 const CGroupContext
*cgroup_context
,
361 char serialization_fd_number
[DECIMAL_STR_MAX(int) + 1];
362 _cleanup_free_
char *subcgroup_path
= NULL
, *log_level
= NULL
, *executor_path
= NULL
;
363 _cleanup_fdset_free_ FDSet
*fdset
= NULL
;
364 _cleanup_fclose_
FILE *f
= NULL
;
369 assert(unit
->manager
);
370 assert(unit
->manager
->executor_fd
>= 0);
375 assert(params
->fds
|| (params
->n_socket_fds
+ params
->n_storage_fds
<= 0));
376 assert(!params
->files_env
); /* We fill this field, ensure it comes NULL-initialized to us */
378 LOG_CONTEXT_PUSH_UNIT(unit
);
380 r
= exec_context_load_environment(unit
, context
, ¶ms
->files_env
);
382 return log_unit_error_errno(unit
, r
, "Failed to load environment files: %m");
384 /* Fork with up-to-date SELinux label database, so the child inherits the up-to-date db
385 and, until the next SELinux policy changes, we save further reloads in future children. */
386 mac_selinux_maybe_reload();
388 /* We won't know the real executable path until we create the mount namespace in the child, but we
389 want to log from the parent, so we use the possibly inaccurate path here. */
390 log_command_line(unit
, "About to execute", command
->path
, command
->argv
);
392 if (params
->cgroup_path
) {
393 r
= exec_params_get_cgroup_path(params
, cgroup_context
, &subcgroup_path
);
395 return log_unit_error_errno(unit
, r
, "Failed to acquire subcgroup path: %m");
397 /* If there's a subcgroup, then let's create it here now (the main cgroup was already
398 * realized by the unit logic) */
400 r
= cg_create(SYSTEMD_CGROUP_CONTROLLER
, subcgroup_path
);
402 return log_unit_error_errno(unit
, r
, "Failed to create subcgroup '%s': %m", subcgroup_path
);
406 /* In order to avoid copy-on-write traps and OOM-kills when pid1's memory.current is above the
407 * child's memory.max, serialize all the state needed to start the unit, and pass it to the
408 * systemd-executor binary. clone() with CLONE_VM + CLONE_VFORK will pause the parent until the exec
409 * and ensure all memory is shared. The child immediately execs the new binary so the delay should
410 * be minimal. Once glibc provides a clone3 wrapper we can switch to that, and clone directly in the
413 r
= open_serialization_file("sd-executor-state", &f
);
415 return log_unit_error_errno(unit
, r
, "Failed to open serialization stream: %m");
421 r
= exec_serialize_invocation(f
, fdset
, context
, command
, params
, runtime
, cgroup_context
);
423 return log_unit_error_errno(unit
, r
, "Failed to serialize parameters: %m");
425 if (fseeko(f
, 0, SEEK_SET
) < 0)
426 return log_unit_error_errno(unit
, errno
, "Failed to reseek on serialization stream: %m");
428 r
= fd_cloexec(fileno(f
), false);
430 return log_unit_error_errno(unit
, r
, "Failed to set O_CLOEXEC on serialization fd: %m");
432 r
= fdset_cloexec(fdset
, false);
434 return log_unit_error_errno(unit
, r
, "Failed to set O_CLOEXEC on serialized fds: %m");
436 r
= log_level_to_string_alloc(log_get_max_level(), &log_level
);
438 return log_unit_error_errno(unit
, r
, "Failed to convert log level to string: %m");
440 r
= fd_get_path(unit
->manager
->executor_fd
, &executor_path
);
442 return log_unit_error_errno(unit
, r
, "Failed to get executor path from fd: %m");
444 xsprintf(serialization_fd_number
, "%i", fileno(f
));
446 /* The executor binary is pinned, to avoid compatibility problems during upgrades. */
447 r
= posix_spawn_wrapper(
448 FORMAT_PROC_FD_PATH(unit
->manager
->executor_fd
),
449 STRV_MAKE(executor_path
,
450 "--deserialize", serialization_fd_number
,
451 "--log-level", log_level
,
452 "--log-target", log_target_to_string(manager_get_executor_log_target(unit
->manager
))),
456 return log_unit_error_errno(unit
, r
, "Failed to spawn executor: %m");
458 log_unit_debug(unit
, "Forked %s as "PID_FMT
, command
->path
, pid
);
460 /* We add the new process to the cgroup both in the child (so that we can be sure that no user code is ever
461 * executed outside of the cgroup) and in the parent (so that we can be sure that when we kill the cgroup the
462 * process will be killed too). */
464 (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER
, subcgroup_path
, pid
);
466 exec_status_start(&command
->exec_status
, pid
);
472 void exec_context_init(ExecContext
*c
) {
475 /* When initializing a bool member to 'true', make sure to serialize in execute-serialize.c using
476 * serialize_bool() instead of serialize_bool_elide(). */
480 .ioprio
= IOPRIO_DEFAULT_CLASS_AND_PRIO
,
481 .cpu_sched_policy
= SCHED_OTHER
,
482 .syslog_priority
= LOG_DAEMON
|LOG_INFO
,
483 .syslog_level_prefix
= true,
484 .ignore_sigpipe
= true,
485 .timer_slack_nsec
= NSEC_INFINITY
,
486 .personality
= PERSONALITY_INVALID
,
487 .timeout_clean_usec
= USEC_INFINITY
,
488 .capability_bounding_set
= CAP_MASK_UNSET
,
489 .restrict_namespaces
= NAMESPACE_FLAGS_INITIAL
,
492 .syscall_errno
= SECCOMP_ERROR_NUMBER_KILL
,
494 .tty_rows
= UINT_MAX
,
495 .tty_cols
= UINT_MAX
,
496 .private_mounts
= -1,
498 .set_login_environment
= -1,
501 FOREACH_ARRAY(d
, c
->directories
, _EXEC_DIRECTORY_TYPE_MAX
)
504 numa_policy_reset(&c
->numa_policy
);
506 assert_cc(NAMESPACE_FLAGS_INITIAL
!= NAMESPACE_FLAGS_ALL
);
509 void exec_context_done(ExecContext
*c
) {
512 c
->environment
= strv_free(c
->environment
);
513 c
->environment_files
= strv_free(c
->environment_files
);
514 c
->pass_environment
= strv_free(c
->pass_environment
);
515 c
->unset_environment
= strv_free(c
->unset_environment
);
517 rlimit_free_all(c
->rlimit
);
519 for (size_t l
= 0; l
< 3; l
++) {
520 c
->stdio_fdname
[l
] = mfree(c
->stdio_fdname
[l
]);
521 c
->stdio_file
[l
] = mfree(c
->stdio_file
[l
]);
524 c
->working_directory
= mfree(c
->working_directory
);
525 c
->root_directory
= mfree(c
->root_directory
);
526 c
->root_image
= mfree(c
->root_image
);
527 c
->root_image_options
= mount_options_free_all(c
->root_image_options
);
528 c
->root_hash
= mfree(c
->root_hash
);
529 c
->root_hash_size
= 0;
530 c
->root_hash_path
= mfree(c
->root_hash_path
);
531 c
->root_hash_sig
= mfree(c
->root_hash_sig
);
532 c
->root_hash_sig_size
= 0;
533 c
->root_hash_sig_path
= mfree(c
->root_hash_sig_path
);
534 c
->root_verity
= mfree(c
->root_verity
);
535 c
->extension_images
= mount_image_free_many(c
->extension_images
, &c
->n_extension_images
);
536 c
->extension_directories
= strv_free(c
->extension_directories
);
537 c
->tty_path
= mfree(c
->tty_path
);
538 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
539 c
->user
= mfree(c
->user
);
540 c
->group
= mfree(c
->group
);
542 c
->supplementary_groups
= strv_free(c
->supplementary_groups
);
544 c
->pam_name
= mfree(c
->pam_name
);
546 c
->read_only_paths
= strv_free(c
->read_only_paths
);
547 c
->read_write_paths
= strv_free(c
->read_write_paths
);
548 c
->inaccessible_paths
= strv_free(c
->inaccessible_paths
);
549 c
->exec_paths
= strv_free(c
->exec_paths
);
550 c
->no_exec_paths
= strv_free(c
->no_exec_paths
);
551 c
->exec_search_path
= strv_free(c
->exec_search_path
);
553 bind_mount_free_many(c
->bind_mounts
, c
->n_bind_mounts
);
554 c
->bind_mounts
= NULL
;
555 c
->n_bind_mounts
= 0;
556 temporary_filesystem_free_many(c
->temporary_filesystems
, c
->n_temporary_filesystems
);
557 c
->temporary_filesystems
= NULL
;
558 c
->n_temporary_filesystems
= 0;
559 c
->mount_images
= mount_image_free_many(c
->mount_images
, &c
->n_mount_images
);
561 cpu_set_reset(&c
->cpu_set
);
562 numa_policy_reset(&c
->numa_policy
);
564 c
->utmp_id
= mfree(c
->utmp_id
);
565 c
->selinux_context
= mfree(c
->selinux_context
);
566 c
->apparmor_profile
= mfree(c
->apparmor_profile
);
567 c
->smack_process_label
= mfree(c
->smack_process_label
);
569 c
->restrict_filesystems
= set_free_free(c
->restrict_filesystems
);
571 c
->syscall_filter
= hashmap_free(c
->syscall_filter
);
572 c
->syscall_archs
= set_free(c
->syscall_archs
);
573 c
->address_families
= set_free(c
->address_families
);
575 FOREACH_ARRAY(d
, c
->directories
, _EXEC_DIRECTORY_TYPE_MAX
)
576 exec_directory_done(d
);
578 c
->log_level_max
= -1;
580 exec_context_free_log_extra_fields(c
);
581 c
->log_filter_allowed_patterns
= set_free_free(c
->log_filter_allowed_patterns
);
582 c
->log_filter_denied_patterns
= set_free_free(c
->log_filter_denied_patterns
);
584 c
->log_ratelimit_interval_usec
= 0;
585 c
->log_ratelimit_burst
= 0;
587 c
->stdin_data
= mfree(c
->stdin_data
);
588 c
->stdin_data_size
= 0;
590 c
->network_namespace_path
= mfree(c
->network_namespace_path
);
591 c
->ipc_namespace_path
= mfree(c
->ipc_namespace_path
);
593 c
->log_namespace
= mfree(c
->log_namespace
);
595 c
->load_credentials
= hashmap_free(c
->load_credentials
);
596 c
->set_credentials
= hashmap_free(c
->set_credentials
);
597 c
->import_credentials
= set_free_free(c
->import_credentials
);
599 c
->root_image_policy
= image_policy_free(c
->root_image_policy
);
600 c
->mount_image_policy
= image_policy_free(c
->mount_image_policy
);
601 c
->extension_image_policy
= image_policy_free(c
->extension_image_policy
);
604 int exec_context_destroy_runtime_directory(const ExecContext
*c
, const char *runtime_prefix
) {
610 FOREACH_ARRAY(i
, c
->directories
[EXEC_DIRECTORY_RUNTIME
].items
, c
->directories
[EXEC_DIRECTORY_RUNTIME
].n_items
) {
611 _cleanup_free_
char *p
= NULL
;
613 if (exec_directory_is_private(c
, EXEC_DIRECTORY_RUNTIME
))
614 p
= path_join(runtime_prefix
, "private", i
->path
);
616 p
= path_join(runtime_prefix
, i
->path
);
620 /* We execute this synchronously, since we need to be sure this is gone when we start the
622 (void) rm_rf(p
, REMOVE_ROOT
);
624 STRV_FOREACH(symlink
, i
->symlinks
) {
625 _cleanup_free_
char *symlink_abs
= NULL
;
627 if (exec_directory_is_private(c
, EXEC_DIRECTORY_RUNTIME
))
628 symlink_abs
= path_join(runtime_prefix
, "private", *symlink
);
630 symlink_abs
= path_join(runtime_prefix
, *symlink
);
634 (void) unlink(symlink_abs
);
641 int exec_context_destroy_mount_ns_dir(Unit
*u
) {
642 _cleanup_free_
char *p
= NULL
;
644 if (!u
|| !MANAGER_IS_SYSTEM(u
->manager
))
647 p
= path_join("/run/systemd/propagate/", u
->id
);
651 /* This is only filled transiently (see mount_in_namespace()), should be empty or even non-existent*/
652 if (rmdir(p
) < 0 && errno
!= ENOENT
)
653 log_unit_debug_errno(u
, errno
, "Unable to remove propagation dir '%s', ignoring: %m", p
);
658 void exec_command_done(ExecCommand
*c
) {
661 c
->path
= mfree(c
->path
);
662 c
->argv
= strv_free(c
->argv
);
665 void exec_command_done_array(ExecCommand
*c
, size_t n
) {
666 FOREACH_ARRAY(i
, c
, n
)
667 exec_command_done(i
);
670 ExecCommand
* exec_command_free_list(ExecCommand
*c
) {
673 while ((i
= LIST_POP(command
, c
))) {
674 exec_command_done(i
);
681 void exec_command_free_array(ExecCommand
**c
, size_t n
) {
682 FOREACH_ARRAY(i
, c
, n
)
683 *i
= exec_command_free_list(*i
);
686 void exec_command_reset_status_array(ExecCommand
*c
, size_t n
) {
687 FOREACH_ARRAY(i
, c
, n
)
688 exec_status_reset(&i
->exec_status
);
691 void exec_command_reset_status_list_array(ExecCommand
**c
, size_t n
) {
692 FOREACH_ARRAY(i
, c
, n
)
693 LIST_FOREACH(command
, z
, *i
)
694 exec_status_reset(&z
->exec_status
);
697 typedef struct InvalidEnvInfo
{
702 static void invalid_env(const char *p
, void *userdata
) {
703 InvalidEnvInfo
*info
= userdata
;
705 log_unit_error(info
->unit
, "Ignoring invalid environment assignment '%s': %s", p
, info
->path
);
708 const char* exec_context_fdname(const ExecContext
*c
, int fd_index
) {
714 if (c
->std_input
!= EXEC_INPUT_NAMED_FD
)
717 return c
->stdio_fdname
[STDIN_FILENO
] ?: "stdin";
720 if (c
->std_output
!= EXEC_OUTPUT_NAMED_FD
)
723 return c
->stdio_fdname
[STDOUT_FILENO
] ?: "stdout";
726 if (c
->std_error
!= EXEC_OUTPUT_NAMED_FD
)
729 return c
->stdio_fdname
[STDERR_FILENO
] ?: "stderr";
736 static int exec_context_load_environment(const Unit
*unit
, const ExecContext
*c
, char ***ret
) {
737 _cleanup_strv_free_
char **v
= NULL
;
743 STRV_FOREACH(i
, c
->environment_files
) {
744 _cleanup_globfree_ glob_t pglob
= {};
753 if (!path_is_absolute(fn
)) {
759 /* Filename supports globbing, take all matching files */
760 r
= safe_glob(fn
, 0, &pglob
);
767 /* When we don't match anything, -ENOENT should be returned */
768 assert(pglob
.gl_pathc
> 0);
770 FOREACH_ARRAY(path
, pglob
.gl_pathv
, pglob
.gl_pathc
) {
771 _cleanup_strv_free_
char **p
= NULL
;
773 r
= load_env_file(NULL
, *path
, &p
);
780 /* Log invalid environment variables with filename */
782 InvalidEnvInfo info
= {
787 p
= strv_env_clean_with_callback(p
, invalid_env
, &info
);
793 char **m
= strv_env_merge(v
, p
);
797 strv_free_and_replace(v
, m
);
807 static bool tty_may_match_dev_console(const char *tty
) {
808 _cleanup_free_
char *resolved
= NULL
;
813 tty
= skip_dev_prefix(tty
);
815 /* trivial identity? */
816 if (streq(tty
, "console"))
819 if (resolve_dev_console(&resolved
) < 0)
820 return true; /* if we could not resolve, assume it may */
822 /* "tty0" means the active VC, so it may be the same sometimes */
823 return path_equal(resolved
, tty
) || (streq(resolved
, "tty0") && tty_is_vc(tty
));
826 static bool exec_context_may_touch_tty(const ExecContext
*ec
) {
829 return ec
->tty_reset
||
831 ec
->tty_vt_disallocate
||
832 is_terminal_input(ec
->std_input
) ||
833 is_terminal_output(ec
->std_output
) ||
834 is_terminal_output(ec
->std_error
);
837 bool exec_context_may_touch_console(const ExecContext
*ec
) {
839 return exec_context_may_touch_tty(ec
) &&
840 tty_may_match_dev_console(exec_context_tty_path(ec
));
843 static void strv_fprintf(FILE *f
, char **l
) {
847 fprintf(f
, " %s", *g
);
850 static void strv_dump(FILE* f
, const char *prefix
, const char *name
, char **strv
) {
855 if (!strv_isempty(strv
)) {
856 fprintf(f
, "%s%s:", prefix
, name
);
857 strv_fprintf(f
, strv
);
862 void exec_params_dump(const ExecParameters
*p
, FILE* f
, const char *prefix
) {
866 prefix
= strempty(prefix
);
869 "%sRuntimeScope: %s\n"
871 "%sSELinuxContextNetwork: %s\n"
872 "%sCgroupSupportedMask: %u\n"
874 "%sCrededentialsDirectory: %s\n"
875 "%sEncryptedCredentialsDirectory: %s\n"
876 "%sConfirmSpawn: %s\n"
877 "%sShallConfirmSpawn: %s\n"
878 "%sWatchdogUSec: " USEC_FMT
"\n"
879 "%sNotifySocket: %s\n"
880 "%sFallbackSmackProcessLabel: %s\n",
881 prefix
, runtime_scope_to_string(p
->runtime_scope
),
883 prefix
, yes_no(p
->selinux_context_net
),
884 prefix
, p
->cgroup_supported
,
885 prefix
, p
->cgroup_path
,
886 prefix
, strempty(p
->received_credentials_directory
),
887 prefix
, strempty(p
->received_encrypted_credentials_directory
),
888 prefix
, strempty(p
->confirm_spawn
),
889 prefix
, yes_no(p
->shall_confirm_spawn
),
890 prefix
, p
->watchdog_usec
,
891 prefix
, strempty(p
->notify_socket
),
892 prefix
, strempty(p
->fallback_smack_process_label
));
894 strv_dump(f
, prefix
, "FdNames", p
->fd_names
);
895 strv_dump(f
, prefix
, "Environment", p
->environment
);
896 strv_dump(f
, prefix
, "Prefix", p
->prefix
);
898 LIST_FOREACH(open_files
, file
, p
->open_files
)
899 fprintf(f
, "%sOpenFile: %s %s", prefix
, file
->path
, open_file_flags_to_string(file
->flags
));
901 strv_dump(f
, prefix
, "FilesEnv", p
->files_env
);
904 void exec_context_dump(const ExecContext
*c
, FILE* f
, const char *prefix
) {
910 prefix
= strempty(prefix
);
914 "%sWorkingDirectory: %s\n"
915 "%sRootDirectory: %s\n"
916 "%sRootEphemeral: %s\n"
917 "%sNonBlocking: %s\n"
919 "%sPrivateDevices: %s\n"
920 "%sProtectKernelTunables: %s\n"
921 "%sProtectKernelModules: %s\n"
922 "%sProtectKernelLogs: %s\n"
923 "%sProtectClock: %s\n"
924 "%sProtectControlGroups: %s\n"
925 "%sPrivateNetwork: %s\n"
926 "%sPrivateUsers: %s\n"
927 "%sProtectHome: %s\n"
928 "%sProtectSystem: %s\n"
929 "%sMountAPIVFS: %s\n"
930 "%sIgnoreSIGPIPE: %s\n"
931 "%sMemoryDenyWriteExecute: %s\n"
932 "%sRestrictRealtime: %s\n"
933 "%sRestrictSUIDSGID: %s\n"
934 "%sKeyringMode: %s\n"
935 "%sProtectHostname: %s\n"
936 "%sProtectProc: %s\n"
937 "%sProcSubset: %s\n",
939 prefix
, empty_to_root(c
->working_directory
),
940 prefix
, empty_to_root(c
->root_directory
),
941 prefix
, yes_no(c
->root_ephemeral
),
942 prefix
, yes_no(c
->non_blocking
),
943 prefix
, yes_no(c
->private_tmp
),
944 prefix
, yes_no(c
->private_devices
),
945 prefix
, yes_no(c
->protect_kernel_tunables
),
946 prefix
, yes_no(c
->protect_kernel_modules
),
947 prefix
, yes_no(c
->protect_kernel_logs
),
948 prefix
, yes_no(c
->protect_clock
),
949 prefix
, yes_no(c
->protect_control_groups
),
950 prefix
, yes_no(c
->private_network
),
951 prefix
, yes_no(c
->private_users
),
952 prefix
, protect_home_to_string(c
->protect_home
),
953 prefix
, protect_system_to_string(c
->protect_system
),
954 prefix
, yes_no(exec_context_get_effective_mount_apivfs(c
)),
955 prefix
, yes_no(c
->ignore_sigpipe
),
956 prefix
, yes_no(c
->memory_deny_write_execute
),
957 prefix
, yes_no(c
->restrict_realtime
),
958 prefix
, yes_no(c
->restrict_suid_sgid
),
959 prefix
, exec_keyring_mode_to_string(c
->keyring_mode
),
960 prefix
, yes_no(c
->protect_hostname
),
961 prefix
, protect_proc_to_string(c
->protect_proc
),
962 prefix
, proc_subset_to_string(c
->proc_subset
));
964 if (c
->set_login_environment
>= 0)
965 fprintf(f
, "%sSetLoginEnvironment: %s\n", prefix
, yes_no(c
->set_login_environment
> 0));
968 fprintf(f
, "%sRootImage: %s\n", prefix
, c
->root_image
);
970 if (c
->root_image_options
) {
971 fprintf(f
, "%sRootImageOptions:", prefix
);
972 LIST_FOREACH(mount_options
, o
, c
->root_image_options
)
973 if (!isempty(o
->options
))
975 partition_designator_to_string(o
->partition_designator
),
981 _cleanup_free_
char *encoded
= NULL
;
982 encoded
= hexmem(c
->root_hash
, c
->root_hash_size
);
984 fprintf(f
, "%sRootHash: %s\n", prefix
, encoded
);
987 if (c
->root_hash_path
)
988 fprintf(f
, "%sRootHash: %s\n", prefix
, c
->root_hash_path
);
990 if (c
->root_hash_sig
) {
991 _cleanup_free_
char *encoded
= NULL
;
993 len
= base64mem(c
->root_hash_sig
, c
->root_hash_sig_size
, &encoded
);
995 fprintf(f
, "%sRootHashSignature: base64:%s\n", prefix
, encoded
);
998 if (c
->root_hash_sig_path
)
999 fprintf(f
, "%sRootHashSignature: %s\n", prefix
, c
->root_hash_sig_path
);
1002 fprintf(f
, "%sRootVerity: %s\n", prefix
, c
->root_verity
);
1004 STRV_FOREACH(e
, c
->environment
)
1005 fprintf(f
, "%sEnvironment: %s\n", prefix
, *e
);
1007 STRV_FOREACH(e
, c
->environment_files
)
1008 fprintf(f
, "%sEnvironmentFile: %s\n", prefix
, *e
);
1010 STRV_FOREACH(e
, c
->pass_environment
)
1011 fprintf(f
, "%sPassEnvironment: %s\n", prefix
, *e
);
1013 STRV_FOREACH(e
, c
->unset_environment
)
1014 fprintf(f
, "%sUnsetEnvironment: %s\n", prefix
, *e
);
1016 fprintf(f
, "%sRuntimeDirectoryPreserve: %s\n", prefix
, exec_preserve_mode_to_string(c
->runtime_directory_preserve_mode
));
1018 for (ExecDirectoryType dt
= 0; dt
< _EXEC_DIRECTORY_TYPE_MAX
; dt
++) {
1019 fprintf(f
, "%s%sMode: %04o\n", prefix
, exec_directory_type_to_string(dt
), c
->directories
[dt
].mode
);
1021 for (size_t i
= 0; i
< c
->directories
[dt
].n_items
; i
++) {
1022 fprintf(f
, "%s%s: %s\n", prefix
, exec_directory_type_to_string(dt
), c
->directories
[dt
].items
[i
].path
);
1024 STRV_FOREACH(d
, c
->directories
[dt
].items
[i
].symlinks
)
1025 fprintf(f
, "%s%s: %s:%s\n", prefix
, exec_directory_type_symlink_to_string(dt
), c
->directories
[dt
].items
[i
].path
, *d
);
1029 fprintf(f
, "%sTimeoutCleanSec: %s\n", prefix
, FORMAT_TIMESPAN(c
->timeout_clean_usec
, USEC_PER_SEC
));
1031 if (c
->memory_ksm
>= 0)
1032 fprintf(f
, "%sMemoryKSM: %s\n", prefix
, yes_no(c
->memory_ksm
> 0));
1035 fprintf(f
, "%sNice: %i\n", prefix
, c
->nice
);
1037 if (c
->oom_score_adjust_set
)
1038 fprintf(f
, "%sOOMScoreAdjust: %i\n", prefix
, c
->oom_score_adjust
);
1040 if (c
->coredump_filter_set
)
1041 fprintf(f
, "%sCoredumpFilter: 0x%"PRIx64
"\n", prefix
, c
->coredump_filter
);
1043 for (unsigned i
= 0; i
< RLIM_NLIMITS
; i
++)
1045 fprintf(f
, "%sLimit%s: " RLIM_FMT
"\n",
1046 prefix
, rlimit_to_string(i
), c
->rlimit
[i
]->rlim_max
);
1047 fprintf(f
, "%sLimit%sSoft: " RLIM_FMT
"\n",
1048 prefix
, rlimit_to_string(i
), c
->rlimit
[i
]->rlim_cur
);
1051 if (c
->ioprio_set
) {
1052 _cleanup_free_
char *class_str
= NULL
;
1054 r
= ioprio_class_to_string_alloc(ioprio_prio_class(c
->ioprio
), &class_str
);
1056 fprintf(f
, "%sIOSchedulingClass: %s\n", prefix
, class_str
);
1058 fprintf(f
, "%sIOPriority: %d\n", prefix
, ioprio_prio_data(c
->ioprio
));
1061 if (c
->cpu_sched_set
) {
1062 _cleanup_free_
char *policy_str
= NULL
;
1064 r
= sched_policy_to_string_alloc(c
->cpu_sched_policy
, &policy_str
);
1066 fprintf(f
, "%sCPUSchedulingPolicy: %s\n", prefix
, policy_str
);
1069 "%sCPUSchedulingPriority: %i\n"
1070 "%sCPUSchedulingResetOnFork: %s\n",
1071 prefix
, c
->cpu_sched_priority
,
1072 prefix
, yes_no(c
->cpu_sched_reset_on_fork
));
1075 if (c
->cpu_set
.set
) {
1076 _cleanup_free_
char *affinity
= NULL
;
1078 affinity
= cpu_set_to_range_string(&c
->cpu_set
);
1079 fprintf(f
, "%sCPUAffinity: %s\n", prefix
, affinity
);
1082 if (mpol_is_valid(numa_policy_get_type(&c
->numa_policy
))) {
1083 _cleanup_free_
char *nodes
= NULL
;
1085 nodes
= cpu_set_to_range_string(&c
->numa_policy
.nodes
);
1086 fprintf(f
, "%sNUMAPolicy: %s\n", prefix
, mpol_to_string(numa_policy_get_type(&c
->numa_policy
)));
1087 fprintf(f
, "%sNUMAMask: %s\n", prefix
, strnull(nodes
));
1090 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
1091 fprintf(f
, "%sTimerSlackNSec: "NSEC_FMT
"\n", prefix
, c
->timer_slack_nsec
);
1094 "%sStandardInput: %s\n"
1095 "%sStandardOutput: %s\n"
1096 "%sStandardError: %s\n",
1097 prefix
, exec_input_to_string(c
->std_input
),
1098 prefix
, exec_output_to_string(c
->std_output
),
1099 prefix
, exec_output_to_string(c
->std_error
));
1101 if (c
->std_input
== EXEC_INPUT_NAMED_FD
)
1102 fprintf(f
, "%sStandardInputFileDescriptorName: %s\n", prefix
, c
->stdio_fdname
[STDIN_FILENO
]);
1103 if (c
->std_output
== EXEC_OUTPUT_NAMED_FD
)
1104 fprintf(f
, "%sStandardOutputFileDescriptorName: %s\n", prefix
, c
->stdio_fdname
[STDOUT_FILENO
]);
1105 if (c
->std_error
== EXEC_OUTPUT_NAMED_FD
)
1106 fprintf(f
, "%sStandardErrorFileDescriptorName: %s\n", prefix
, c
->stdio_fdname
[STDERR_FILENO
]);
1108 if (c
->std_input
== EXEC_INPUT_FILE
)
1109 fprintf(f
, "%sStandardInputFile: %s\n", prefix
, c
->stdio_file
[STDIN_FILENO
]);
1110 if (c
->std_output
== EXEC_OUTPUT_FILE
)
1111 fprintf(f
, "%sStandardOutputFile: %s\n", prefix
, c
->stdio_file
[STDOUT_FILENO
]);
1112 if (c
->std_output
== EXEC_OUTPUT_FILE_APPEND
)
1113 fprintf(f
, "%sStandardOutputFileToAppend: %s\n", prefix
, c
->stdio_file
[STDOUT_FILENO
]);
1114 if (c
->std_output
== EXEC_OUTPUT_FILE_TRUNCATE
)
1115 fprintf(f
, "%sStandardOutputFileToTruncate: %s\n", prefix
, c
->stdio_file
[STDOUT_FILENO
]);
1116 if (c
->std_error
== EXEC_OUTPUT_FILE
)
1117 fprintf(f
, "%sStandardErrorFile: %s\n", prefix
, c
->stdio_file
[STDERR_FILENO
]);
1118 if (c
->std_error
== EXEC_OUTPUT_FILE_APPEND
)
1119 fprintf(f
, "%sStandardErrorFileToAppend: %s\n", prefix
, c
->stdio_file
[STDERR_FILENO
]);
1120 if (c
->std_error
== EXEC_OUTPUT_FILE_TRUNCATE
)
1121 fprintf(f
, "%sStandardErrorFileToTruncate: %s\n", prefix
, c
->stdio_file
[STDERR_FILENO
]);
1127 "%sTTYVHangup: %s\n"
1128 "%sTTYVTDisallocate: %s\n"
1130 "%sTTYColumns: %u\n",
1131 prefix
, c
->tty_path
,
1132 prefix
, yes_no(c
->tty_reset
),
1133 prefix
, yes_no(c
->tty_vhangup
),
1134 prefix
, yes_no(c
->tty_vt_disallocate
),
1135 prefix
, c
->tty_rows
,
1136 prefix
, c
->tty_cols
);
1138 if (IN_SET(c
->std_output
,
1140 EXEC_OUTPUT_JOURNAL
,
1141 EXEC_OUTPUT_KMSG_AND_CONSOLE
,
1142 EXEC_OUTPUT_JOURNAL_AND_CONSOLE
) ||
1143 IN_SET(c
->std_error
,
1145 EXEC_OUTPUT_JOURNAL
,
1146 EXEC_OUTPUT_KMSG_AND_CONSOLE
,
1147 EXEC_OUTPUT_JOURNAL_AND_CONSOLE
)) {
1149 _cleanup_free_
char *fac_str
= NULL
, *lvl_str
= NULL
;
1151 r
= log_facility_unshifted_to_string_alloc(c
->syslog_priority
>> 3, &fac_str
);
1153 fprintf(f
, "%sSyslogFacility: %s\n", prefix
, fac_str
);
1155 r
= log_level_to_string_alloc(LOG_PRI(c
->syslog_priority
), &lvl_str
);
1157 fprintf(f
, "%sSyslogLevel: %s\n", prefix
, lvl_str
);
1160 if (c
->log_level_max
>= 0) {
1161 _cleanup_free_
char *t
= NULL
;
1163 (void) log_level_to_string_alloc(c
->log_level_max
, &t
);
1165 fprintf(f
, "%sLogLevelMax: %s\n", prefix
, strna(t
));
1168 if (c
->log_ratelimit_interval_usec
> 0)
1170 "%sLogRateLimitIntervalSec: %s\n",
1171 prefix
, FORMAT_TIMESPAN(c
->log_ratelimit_interval_usec
, USEC_PER_SEC
));
1173 if (c
->log_ratelimit_burst
> 0)
1174 fprintf(f
, "%sLogRateLimitBurst: %u\n", prefix
, c
->log_ratelimit_burst
);
1176 if (!set_isempty(c
->log_filter_allowed_patterns
) || !set_isempty(c
->log_filter_denied_patterns
)) {
1177 fprintf(f
, "%sLogFilterPatterns:", prefix
);
1180 SET_FOREACH(pattern
, c
->log_filter_allowed_patterns
)
1181 fprintf(f
, " %s", pattern
);
1182 SET_FOREACH(pattern
, c
->log_filter_denied_patterns
)
1183 fprintf(f
, " ~%s", pattern
);
1187 FOREACH_ARRAY(field
, c
->log_extra_fields
, c
->n_log_extra_fields
) {
1188 fprintf(f
, "%sLogExtraFields: ", prefix
);
1189 fwrite(field
->iov_base
, 1, field
->iov_len
, f
);
1193 if (c
->log_namespace
)
1194 fprintf(f
, "%sLogNamespace: %s\n", prefix
, c
->log_namespace
);
1196 if (c
->secure_bits
) {
1197 _cleanup_free_
char *str
= NULL
;
1199 r
= secure_bits_to_string_alloc(c
->secure_bits
, &str
);
1201 fprintf(f
, "%sSecure Bits: %s\n", prefix
, str
);
1204 if (c
->capability_bounding_set
!= CAP_MASK_UNSET
) {
1205 _cleanup_free_
char *str
= NULL
;
1207 r
= capability_set_to_string(c
->capability_bounding_set
, &str
);
1209 fprintf(f
, "%sCapabilityBoundingSet: %s\n", prefix
, str
);
1212 if (c
->capability_ambient_set
!= 0) {
1213 _cleanup_free_
char *str
= NULL
;
1215 r
= capability_set_to_string(c
->capability_ambient_set
, &str
);
1217 fprintf(f
, "%sAmbientCapabilities: %s\n", prefix
, str
);
1221 fprintf(f
, "%sUser: %s\n", prefix
, c
->user
);
1223 fprintf(f
, "%sGroup: %s\n", prefix
, c
->group
);
1225 fprintf(f
, "%sDynamicUser: %s\n", prefix
, yes_no(c
->dynamic_user
));
1227 strv_dump(f
, prefix
, "SupplementaryGroups", c
->supplementary_groups
);
1230 fprintf(f
, "%sPAMName: %s\n", prefix
, c
->pam_name
);
1232 strv_dump(f
, prefix
, "ReadWritePaths", c
->read_write_paths
);
1233 strv_dump(f
, prefix
, "ReadOnlyPaths", c
->read_only_paths
);
1234 strv_dump(f
, prefix
, "InaccessiblePaths", c
->inaccessible_paths
);
1235 strv_dump(f
, prefix
, "ExecPaths", c
->exec_paths
);
1236 strv_dump(f
, prefix
, "NoExecPaths", c
->no_exec_paths
);
1237 strv_dump(f
, prefix
, "ExecSearchPath", c
->exec_search_path
);
1239 FOREACH_ARRAY(mount
, c
->bind_mounts
, c
->n_bind_mounts
)
1240 fprintf(f
, "%s%s: %s%s:%s:%s\n", prefix
,
1241 mount
->read_only
? "BindReadOnlyPaths" : "BindPaths",
1242 mount
->ignore_enoent
? "-": "",
1245 mount
->recursive
? "rbind" : "norbind");
1247 FOREACH_ARRAY(tmpfs
, c
->temporary_filesystems
, c
->n_temporary_filesystems
)
1248 fprintf(f
, "%sTemporaryFileSystem: %s%s%s\n", prefix
,
1250 isempty(tmpfs
->options
) ? "" : ":",
1251 strempty(tmpfs
->options
));
1255 "%sUtmpIdentifier: %s\n",
1256 prefix
, c
->utmp_id
);
1258 if (c
->selinux_context
)
1260 "%sSELinuxContext: %s%s\n",
1261 prefix
, c
->selinux_context_ignore
? "-" : "", c
->selinux_context
);
1263 if (c
->apparmor_profile
)
1265 "%sAppArmorProfile: %s%s\n",
1266 prefix
, c
->apparmor_profile_ignore
? "-" : "", c
->apparmor_profile
);
1268 if (c
->smack_process_label
)
1270 "%sSmackProcessLabel: %s%s\n",
1271 prefix
, c
->smack_process_label_ignore
? "-" : "", c
->smack_process_label
);
1273 if (c
->personality
!= PERSONALITY_INVALID
)
1275 "%sPersonality: %s\n",
1276 prefix
, strna(personality_to_string(c
->personality
)));
1279 "%sLockPersonality: %s\n",
1280 prefix
, yes_no(c
->lock_personality
));
1282 if (c
->syscall_filter
) {
1284 "%sSystemCallFilter: ",
1287 if (!c
->syscall_allow_list
)
1293 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_filter
) {
1294 _cleanup_free_
char *name
= NULL
;
1295 const char *errno_name
= NULL
;
1296 int num
= PTR_TO_INT(val
);
1303 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
1304 fputs(strna(name
), f
);
1307 errno_name
= seccomp_errno_or_action_to_string(num
);
1309 fprintf(f
, ":%s", errno_name
);
1311 fprintf(f
, ":%d", num
);
1319 if (c
->syscall_archs
) {
1321 "%sSystemCallArchitectures:",
1326 SET_FOREACH(id
, c
->syscall_archs
)
1327 fprintf(f
, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1)));
1332 if (exec_context_restrict_namespaces_set(c
)) {
1333 _cleanup_free_
char *s
= NULL
;
1335 r
= namespace_flags_to_string(c
->restrict_namespaces
, &s
);
1337 fprintf(f
, "%sRestrictNamespaces: %s\n",
1342 if (exec_context_restrict_filesystems_set(c
)) {
1344 SET_FOREACH(fs
, c
->restrict_filesystems
)
1345 fprintf(f
, "%sRestrictFileSystems: %s\n", prefix
, fs
);
1349 if (c
->network_namespace_path
)
1351 "%sNetworkNamespacePath: %s\n",
1352 prefix
, c
->network_namespace_path
);
1354 if (c
->syscall_errno
> 0) {
1355 fprintf(f
, "%sSystemCallErrorNumber: ", prefix
);
1358 const char *errno_name
= seccomp_errno_or_action_to_string(c
->syscall_errno
);
1360 fputs(errno_name
, f
);
1362 fprintf(f
, "%d", c
->syscall_errno
);
1367 FOREACH_ARRAY(mount
, c
->mount_images
, c
->n_mount_images
) {
1368 fprintf(f
, "%sMountImages: %s%s:%s", prefix
,
1369 mount
->ignore_enoent
? "-": "",
1371 mount
->destination
);
1372 LIST_FOREACH(mount_options
, o
, mount
->mount_options
)
1373 fprintf(f
, ":%s:%s",
1374 partition_designator_to_string(o
->partition_designator
),
1375 strempty(o
->options
));
1379 FOREACH_ARRAY(mount
, c
->extension_images
, c
->n_extension_images
) {
1380 fprintf(f
, "%sExtensionImages: %s%s", prefix
,
1381 mount
->ignore_enoent
? "-": "",
1383 LIST_FOREACH(mount_options
, o
, mount
->mount_options
)
1384 fprintf(f
, ":%s:%s",
1385 partition_designator_to_string(o
->partition_designator
),
1386 strempty(o
->options
));
1390 strv_dump(f
, prefix
, "ExtensionDirectories", c
->extension_directories
);
1393 bool exec_context_maintains_privileges(const ExecContext
*c
) {
1396 /* Returns true if the process forked off would run under
1397 * an unchanged UID or as root. */
1402 if (streq(c
->user
, "root") || streq(c
->user
, "0"))
1408 int exec_context_get_effective_ioprio(const ExecContext
*c
) {
1416 p
= ioprio_get(IOPRIO_WHO_PROCESS
, 0);
1418 return IOPRIO_DEFAULT_CLASS_AND_PRIO
;
1420 return ioprio_normalize(p
);
1423 bool exec_context_get_effective_mount_apivfs(const ExecContext
*c
) {
1426 /* Explicit setting wins */
1427 if (c
->mount_apivfs_set
)
1428 return c
->mount_apivfs
;
1430 /* Default to "yes" if root directory or image are specified */
1431 if (exec_context_with_rootfs(c
))
1437 void exec_context_free_log_extra_fields(ExecContext
*c
) {
1440 FOREACH_ARRAY(field
, c
->log_extra_fields
, c
->n_log_extra_fields
)
1441 free(field
->iov_base
);
1443 c
->log_extra_fields
= mfree(c
->log_extra_fields
);
1444 c
->n_log_extra_fields
= 0;
1447 void exec_context_revert_tty(ExecContext
*c
) {
1448 _cleanup_close_
int fd
= -EBADF
;
1455 /* First, reset the TTY (possibly kicking everybody else from the TTY) */
1456 exec_context_tty_reset(c
, NULL
);
1458 /* And then undo what chown_terminal() did earlier. Note that we only do this if we have a path
1459 * configured. If the TTY was passed to us as file descriptor we assume the TTY is opened and managed
1460 * by whoever passed it to us and thus knows better when and how to chmod()/chown() it back. */
1461 if (!exec_context_may_touch_tty(c
))
1464 path
= exec_context_tty_path(c
);
1468 fd
= open(path
, O_PATH
|O_CLOEXEC
);
1470 return (void) log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_WARNING
, errno
,
1471 "Failed to open TTY inode of '%s' to adjust ownership/access mode, ignoring: %m",
1474 if (fstat(fd
, &st
) < 0)
1475 return (void) log_warning_errno(errno
, "Failed to stat TTY '%s', ignoring: %m", path
);
1477 /* Let's add a superficial check that we only do this for stuff that looks like a TTY. We only check
1478 * if things are a character device, since a proper check either means we'd have to open the TTY and
1479 * use isatty(), but we'd rather not do that since opening TTYs comes with all kinds of side-effects
1480 * and is slow. Or we'd have to hardcode dev_t major information, which we'd rather avoid. Why bother
1481 * with this at all? → https://github.com/systemd/systemd/issues/19213 */
1482 if (!S_ISCHR(st
.st_mode
))
1483 return log_warning("Configured TTY '%s' is not actually a character device, ignoring.", path
);
1485 r
= fchmod_and_chown(fd
, TTY_MODE
, 0, TTY_GID
);
1487 log_warning_errno(r
, "Failed to reset TTY ownership/access mode of %s, ignoring: %m", path
);
1490 int exec_context_get_clean_directories(
1496 _cleanup_strv_free_
char **l
= NULL
;
1503 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++) {
1504 if (!FLAGS_SET(mask
, 1U << t
))
1510 FOREACH_ARRAY(i
, c
->directories
[t
].items
, c
->directories
[t
].n_items
) {
1513 j
= path_join(prefix
[t
], i
->path
);
1517 r
= strv_consume(&l
, j
);
1521 /* Also remove private directories unconditionally. */
1522 if (t
!= EXEC_DIRECTORY_CONFIGURATION
) {
1523 j
= path_join(prefix
[t
], "private", i
->path
);
1527 r
= strv_consume(&l
, j
);
1532 STRV_FOREACH(symlink
, i
->symlinks
) {
1533 j
= path_join(prefix
[t
], *symlink
);
1537 r
= strv_consume(&l
, j
);
1548 int exec_context_get_clean_mask(ExecContext
*c
, ExecCleanMask
*ret
) {
1549 ExecCleanMask mask
= 0;
1554 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++)
1555 if (c
->directories
[t
].n_items
> 0)
1562 int exec_context_get_oom_score_adjust(const ExecContext
*c
) {
1567 if (c
->oom_score_adjust_set
)
1568 return c
->oom_score_adjust
;
1570 r
= get_oom_score_adjust(&n
);
1572 log_debug_errno(r
, "Failed to read /proc/self/oom_score_adj, ignoring: %m");
1577 uint64_t exec_context_get_coredump_filter(const ExecContext
*c
) {
1578 _cleanup_free_
char *t
= NULL
;
1579 uint64_t n
= COREDUMP_FILTER_MASK_DEFAULT
;
1584 if (c
->coredump_filter_set
)
1585 return c
->coredump_filter
;
1587 r
= read_one_line_file("/proc/self/coredump_filter", &t
);
1589 log_debug_errno(r
, "Failed to read /proc/self/coredump_filter, ignoring: %m");
1591 r
= safe_atoux64(t
, &n
);
1593 log_debug_errno(r
, "Failed to parse \"%s\" from /proc/self/coredump_filter, ignoring: %m", t
);
1599 int exec_context_get_nice(const ExecContext
*c
) {
1608 n
= getpriority(PRIO_PROCESS
, 0);
1610 log_debug_errno(errno
, "Failed to get process nice value, ignoring: %m");
1617 int exec_context_get_cpu_sched_policy(const ExecContext
*c
) {
1622 if (c
->cpu_sched_set
)
1623 return c
->cpu_sched_policy
;
1625 n
= sched_getscheduler(0);
1627 log_debug_errno(errno
, "Failed to get scheduler policy, ignoring: %m");
1629 return n
< 0 ? SCHED_OTHER
: n
;
1632 int exec_context_get_cpu_sched_priority(const ExecContext
*c
) {
1633 struct sched_param p
= {};
1638 if (c
->cpu_sched_set
)
1639 return c
->cpu_sched_priority
;
1641 r
= sched_getparam(0, &p
);
1643 log_debug_errno(errno
, "Failed to get scheduler priority, ignoring: %m");
1645 return r
>= 0 ? p
.sched_priority
: 0;
1648 uint64_t exec_context_get_timer_slack_nsec(const ExecContext
*c
) {
1653 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
1654 return c
->timer_slack_nsec
;
1656 r
= prctl(PR_GET_TIMERSLACK
);
1658 log_debug_errno(r
, "Failed to get timer slack, ignoring: %m");
1660 return (uint64_t) MAX(r
, 0);
1663 char** exec_context_get_syscall_filter(const ExecContext
*c
) {
1664 _cleanup_strv_free_
char **l
= NULL
;
1670 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_filter
) {
1671 _cleanup_free_
char *name
= NULL
;
1672 const char *e
= NULL
;
1674 int num
= PTR_TO_INT(val
);
1676 if (c
->syscall_allow_list
&& num
>= 0)
1677 /* syscall with num >= 0 in allow-list is denied. */
1680 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
1685 e
= seccomp_errno_or_action_to_string(num
);
1687 s
= strjoin(name
, ":", e
);
1691 if (asprintf(&s
, "%s:%d", name
, num
) < 0)
1697 if (strv_consume(&l
, s
) < 0)
1704 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1707 char** exec_context_get_syscall_archs(const ExecContext
*c
) {
1708 _cleanup_strv_free_
char **l
= NULL
;
1714 SET_FOREACH(id
, c
->syscall_archs
) {
1717 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
1721 if (strv_extend(&l
, name
) < 0)
1728 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1731 char** exec_context_get_syscall_log(const ExecContext
*c
) {
1732 _cleanup_strv_free_
char **l
= NULL
;
1738 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_log
) {
1741 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
1745 if (strv_consume(&l
, name
) < 0)
1752 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1755 char** exec_context_get_address_families(const ExecContext
*c
) {
1756 _cleanup_strv_free_
char **l
= NULL
;
1761 SET_FOREACH(af
, c
->address_families
) {
1764 name
= af_to_name(PTR_TO_INT(af
));
1768 if (strv_extend(&l
, name
) < 0)
1774 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1777 char** exec_context_get_restrict_filesystems(const ExecContext
*c
) {
1778 _cleanup_strv_free_
char **l
= NULL
;
1783 l
= set_get_strv(c
->restrict_filesystems
);
1790 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1793 void exec_status_start(ExecStatus
*s
, pid_t pid
) {
1800 dual_timestamp_get(&s
->start_timestamp
);
1803 void exec_status_exit(ExecStatus
*s
, const ExecContext
*context
, pid_t pid
, int code
, int status
) {
1811 dual_timestamp_get(&s
->exit_timestamp
);
1816 if (context
&& context
->utmp_id
)
1817 (void) utmp_put_dead_process(context
->utmp_id
, pid
, code
, status
);
1820 void exec_status_reset(ExecStatus
*s
) {
1823 *s
= (ExecStatus
) {};
1826 void exec_status_dump(const ExecStatus
*s
, FILE *f
, const char *prefix
) {
1833 prefix
= strempty(prefix
);
1836 "%sPID: "PID_FMT
"\n",
1839 if (dual_timestamp_is_set(&s
->start_timestamp
))
1841 "%sStart Timestamp: %s\n",
1842 prefix
, FORMAT_TIMESTAMP(s
->start_timestamp
.realtime
));
1844 if (dual_timestamp_is_set(&s
->exit_timestamp
))
1846 "%sExit Timestamp: %s\n"
1848 "%sExit Status: %i\n",
1849 prefix
, FORMAT_TIMESTAMP(s
->exit_timestamp
.realtime
),
1850 prefix
, sigchld_code_to_string(s
->code
),
1854 static void exec_command_dump(ExecCommand
*c
, FILE *f
, const char *prefix
) {
1855 _cleanup_free_
char *cmd
= NULL
;
1856 const char *prefix2
;
1861 prefix
= strempty(prefix
);
1862 prefix2
= strjoina(prefix
, "\t");
1864 cmd
= quote_command_line(c
->argv
, SHELL_ESCAPE_EMPTY
);
1867 "%sCommand Line: %s\n",
1868 prefix
, strnull(cmd
));
1870 exec_status_dump(&c
->exec_status
, f
, prefix2
);
1873 void exec_command_dump_list(ExecCommand
*c
, FILE *f
, const char *prefix
) {
1876 prefix
= strempty(prefix
);
1878 LIST_FOREACH(command
, i
, c
)
1879 exec_command_dump(i
, f
, prefix
);
1882 void exec_command_append_list(ExecCommand
**l
, ExecCommand
*e
) {
1889 /* It's kind of important, that we keep the order here */
1890 end
= LIST_FIND_TAIL(command
, *l
);
1891 LIST_INSERT_AFTER(command
, *l
, end
, e
);
1896 int exec_command_set(ExecCommand
*c
, const char *path
, ...) {
1904 l
= strv_new_ap(path
, ap
);
1916 free_and_replace(c
->path
, p
);
1918 return strv_free_and_replace(c
->argv
, l
);
1921 int exec_command_append(ExecCommand
*c
, const char *path
, ...) {
1922 _cleanup_strv_free_
char **l
= NULL
;
1930 l
= strv_new_ap(path
, ap
);
1936 r
= strv_extend_strv(&c
->argv
, l
, false);
1943 static char *destroy_tree(char *path
) {
1947 if (!path_equal(path
, RUN_SYSTEMD_EMPTY
)) {
1948 log_debug("Spawning process to nuke '%s'", path
);
1950 (void) asynchronous_rm_rf(path
, REMOVE_ROOT
|REMOVE_SUBVOLUME
|REMOVE_PHYSICAL
);
1956 void exec_shared_runtime_done(ExecSharedRuntime
*rt
) {
1961 (void) hashmap_remove(rt
->manager
->exec_shared_runtime_by_id
, rt
->id
);
1963 rt
->id
= mfree(rt
->id
);
1964 rt
->tmp_dir
= mfree(rt
->tmp_dir
);
1965 rt
->var_tmp_dir
= mfree(rt
->var_tmp_dir
);
1966 safe_close_pair(rt
->netns_storage_socket
);
1967 safe_close_pair(rt
->ipcns_storage_socket
);
1970 static ExecSharedRuntime
* exec_shared_runtime_free(ExecSharedRuntime
*rt
) {
1971 exec_shared_runtime_done(rt
);
1976 DEFINE_TRIVIAL_UNREF_FUNC(ExecSharedRuntime
, exec_shared_runtime
, exec_shared_runtime_free
);
1977 DEFINE_TRIVIAL_CLEANUP_FUNC(ExecSharedRuntime
*, exec_shared_runtime_free
);
1979 ExecSharedRuntime
* exec_shared_runtime_destroy(ExecSharedRuntime
*rt
) {
1983 assert(rt
->n_ref
> 0);
1989 rt
->tmp_dir
= destroy_tree(rt
->tmp_dir
);
1990 rt
->var_tmp_dir
= destroy_tree(rt
->var_tmp_dir
);
1992 return exec_shared_runtime_free(rt
);
1995 static int exec_shared_runtime_allocate(ExecSharedRuntime
**ret
, const char *id
) {
1996 _cleanup_free_
char *id_copy
= NULL
;
1997 ExecSharedRuntime
*n
;
2001 id_copy
= strdup(id
);
2005 n
= new(ExecSharedRuntime
, 1);
2009 *n
= (ExecSharedRuntime
) {
2010 .id
= TAKE_PTR(id_copy
),
2011 .netns_storage_socket
= EBADF_PAIR
,
2012 .ipcns_storage_socket
= EBADF_PAIR
,
2019 static int exec_shared_runtime_add(
2024 int netns_storage_socket
[2],
2025 int ipcns_storage_socket
[2],
2026 ExecSharedRuntime
**ret
) {
2028 _cleanup_(exec_shared_runtime_freep
) ExecSharedRuntime
*rt
= NULL
;
2034 /* tmp_dir, var_tmp_dir, {net,ipc}ns_storage_socket fds are donated on success */
2036 r
= exec_shared_runtime_allocate(&rt
, id
);
2040 r
= hashmap_ensure_put(&m
->exec_shared_runtime_by_id
, &string_hash_ops
, rt
->id
, rt
);
2044 assert(!!rt
->tmp_dir
== !!rt
->var_tmp_dir
); /* We require both to be set together */
2045 rt
->tmp_dir
= TAKE_PTR(*tmp_dir
);
2046 rt
->var_tmp_dir
= TAKE_PTR(*var_tmp_dir
);
2048 if (netns_storage_socket
) {
2049 rt
->netns_storage_socket
[0] = TAKE_FD(netns_storage_socket
[0]);
2050 rt
->netns_storage_socket
[1] = TAKE_FD(netns_storage_socket
[1]);
2053 if (ipcns_storage_socket
) {
2054 rt
->ipcns_storage_socket
[0] = TAKE_FD(ipcns_storage_socket
[0]);
2055 rt
->ipcns_storage_socket
[1] = TAKE_FD(ipcns_storage_socket
[1]);
2062 /* do not remove created ExecSharedRuntime object when the operation succeeds. */
2067 static int exec_shared_runtime_make(
2069 const ExecContext
*c
,
2071 ExecSharedRuntime
**ret
) {
2073 _cleanup_(namespace_cleanup_tmpdirp
) char *tmp_dir
= NULL
, *var_tmp_dir
= NULL
;
2074 _cleanup_close_pair_
int netns_storage_socket
[2] = EBADF_PAIR
, ipcns_storage_socket
[2] = EBADF_PAIR
;
2081 /* It is not necessary to create ExecSharedRuntime object. */
2082 if (!exec_needs_network_namespace(c
) && !exec_needs_ipc_namespace(c
) && !c
->private_tmp
) {
2087 if (c
->private_tmp
&&
2088 !(prefixed_path_strv_contains(c
->inaccessible_paths
, "/tmp") &&
2089 (prefixed_path_strv_contains(c
->inaccessible_paths
, "/var/tmp") ||
2090 prefixed_path_strv_contains(c
->inaccessible_paths
, "/var")))) {
2091 r
= setup_tmp_dirs(id
, &tmp_dir
, &var_tmp_dir
);
2096 if (exec_needs_network_namespace(c
)) {
2097 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, netns_storage_socket
) < 0)
2101 if (exec_needs_ipc_namespace(c
)) {
2102 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, ipcns_storage_socket
) < 0)
2106 r
= exec_shared_runtime_add(m
, id
, &tmp_dir
, &var_tmp_dir
, netns_storage_socket
, ipcns_storage_socket
, ret
);
2113 int exec_shared_runtime_acquire(Manager
*m
, const ExecContext
*c
, const char *id
, bool create
, ExecSharedRuntime
**ret
) {
2114 ExecSharedRuntime
*rt
;
2121 rt
= hashmap_get(m
->exec_shared_runtime_by_id
, id
);
2123 /* We already have an ExecSharedRuntime object, let's increase the ref count and reuse it */
2131 /* If not found, then create a new object. */
2132 r
= exec_shared_runtime_make(m
, c
, id
, &rt
);
2136 /* When r == 0, it is not necessary to create ExecSharedRuntime object. */
2142 /* increment reference counter. */
2148 int exec_shared_runtime_serialize(const Manager
*m
, FILE *f
, FDSet
*fds
) {
2149 ExecSharedRuntime
*rt
;
2155 HASHMAP_FOREACH(rt
, m
->exec_shared_runtime_by_id
) {
2156 fprintf(f
, "exec-runtime=%s", rt
->id
);
2159 fprintf(f
, " tmp-dir=%s", rt
->tmp_dir
);
2161 if (rt
->var_tmp_dir
)
2162 fprintf(f
, " var-tmp-dir=%s", rt
->var_tmp_dir
);
2164 if (rt
->netns_storage_socket
[0] >= 0) {
2167 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[0]);
2171 fprintf(f
, " netns-socket-0=%i", copy
);
2174 if (rt
->netns_storage_socket
[1] >= 0) {
2177 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[1]);
2181 fprintf(f
, " netns-socket-1=%i", copy
);
2184 if (rt
->ipcns_storage_socket
[0] >= 0) {
2187 copy
= fdset_put_dup(fds
, rt
->ipcns_storage_socket
[0]);
2191 fprintf(f
, " ipcns-socket-0=%i", copy
);
2194 if (rt
->ipcns_storage_socket
[1] >= 0) {
2197 copy
= fdset_put_dup(fds
, rt
->ipcns_storage_socket
[1]);
2201 fprintf(f
, " ipcns-socket-1=%i", copy
);
2210 int exec_shared_runtime_deserialize_compat(Unit
*u
, const char *key
, const char *value
, FDSet
*fds
) {
2211 _cleanup_(exec_shared_runtime_freep
) ExecSharedRuntime
*rt_create
= NULL
;
2212 ExecSharedRuntime
*rt
= NULL
;
2215 /* This is for the migration from old (v237 or earlier) deserialization text.
2216 * Due to the bug #7790, this may not work with the units that use JoinsNamespaceOf=.
2217 * Even if the ExecSharedRuntime object originally created by the other unit, we cannot judge
2218 * so or not from the serialized text, then we always creates a new object owned by this. */
2224 /* Manager manages ExecSharedRuntime objects by the unit id.
2225 * So, we omit the serialized text when the unit does not have id (yet?)... */
2226 if (isempty(u
->id
)) {
2227 log_unit_debug(u
, "Invocation ID not found. Dropping runtime parameter.");
2232 if (hashmap_ensure_allocated(&u
->manager
->exec_shared_runtime_by_id
, &string_hash_ops
) < 0)
2235 rt
= hashmap_get(u
->manager
->exec_shared_runtime_by_id
, u
->id
);
2238 if (exec_shared_runtime_allocate(&rt_create
, u
->id
) < 0)
2244 if (streq(key
, "tmp-dir")) {
2245 if (free_and_strdup_warn(&rt
->tmp_dir
, value
) < 0)
2248 } else if (streq(key
, "var-tmp-dir")) {
2249 if (free_and_strdup_warn(&rt
->var_tmp_dir
, value
) < 0)
2252 } else if (streq(key
, "netns-socket-0")) {
2254 safe_close(rt
->netns_storage_socket
[0]);
2255 rt
->netns_storage_socket
[0] = deserialize_fd(fds
, value
);
2256 if (rt
->netns_storage_socket
[0] < 0)
2259 } else if (streq(key
, "netns-socket-1")) {
2261 safe_close(rt
->netns_storage_socket
[1]);
2262 rt
->netns_storage_socket
[1] = deserialize_fd(fds
, value
);
2263 if (rt
->netns_storage_socket
[1] < 0)
2268 /* If the object is newly created, then put it to the hashmap which manages ExecSharedRuntime objects. */
2269 if (rt_create
&& u
->manager
) {
2270 r
= hashmap_put(u
->manager
->exec_shared_runtime_by_id
, rt_create
->id
, rt_create
);
2272 log_unit_debug_errno(u
, r
, "Failed to put runtime parameter to manager's storage: %m");
2276 rt_create
->manager
= u
->manager
;
2279 TAKE_PTR(rt_create
);
2285 int exec_shared_runtime_deserialize_one(Manager
*m
, const char *value
, FDSet
*fds
) {
2286 _cleanup_free_
char *tmp_dir
= NULL
, *var_tmp_dir
= NULL
;
2288 int r
, netns_fdpair
[] = {-1, -1}, ipcns_fdpair
[] = {-1, -1};
2289 const char *p
, *v
= ASSERT_PTR(value
);
2295 n
= strcspn(v
, " ");
2296 id
= strndupa_safe(v
, n
);
2301 v
= startswith(p
, "tmp-dir=");
2303 n
= strcspn(v
, " ");
2304 tmp_dir
= strndup(v
, n
);
2312 v
= startswith(p
, "var-tmp-dir=");
2314 n
= strcspn(v
, " ");
2315 var_tmp_dir
= strndup(v
, n
);
2323 v
= startswith(p
, "netns-socket-0=");
2327 n
= strcspn(v
, " ");
2328 buf
= strndupa_safe(v
, n
);
2330 netns_fdpair
[0] = deserialize_fd(fds
, buf
);
2331 if (netns_fdpair
[0] < 0)
2332 return netns_fdpair
[0];
2338 v
= startswith(p
, "netns-socket-1=");
2342 n
= strcspn(v
, " ");
2343 buf
= strndupa_safe(v
, n
);
2345 netns_fdpair
[1] = deserialize_fd(fds
, buf
);
2346 if (netns_fdpair
[1] < 0)
2347 return netns_fdpair
[1];
2353 v
= startswith(p
, "ipcns-socket-0=");
2357 n
= strcspn(v
, " ");
2358 buf
= strndupa_safe(v
, n
);
2360 ipcns_fdpair
[0] = deserialize_fd(fds
, buf
);
2361 if (ipcns_fdpair
[0] < 0)
2362 return ipcns_fdpair
[0];
2368 v
= startswith(p
, "ipcns-socket-1=");
2372 n
= strcspn(v
, " ");
2373 buf
= strndupa_safe(v
, n
);
2375 ipcns_fdpair
[1] = deserialize_fd(fds
, buf
);
2376 if (ipcns_fdpair
[1] < 0)
2377 return ipcns_fdpair
[1];
2381 r
= exec_shared_runtime_add(m
, id
, &tmp_dir
, &var_tmp_dir
, netns_fdpair
, ipcns_fdpair
, NULL
);
2383 return log_debug_errno(r
, "Failed to add exec-runtime: %m");
2387 void exec_shared_runtime_vacuum(Manager
*m
) {
2388 ExecSharedRuntime
*rt
;
2392 /* Free unreferenced ExecSharedRuntime objects. This is used after manager deserialization process. */
2394 HASHMAP_FOREACH(rt
, m
->exec_shared_runtime_by_id
) {
2398 (void) exec_shared_runtime_free(rt
);
2402 int exec_runtime_make(
2404 const ExecContext
*context
,
2405 ExecSharedRuntime
*shared
,
2406 DynamicCreds
*creds
,
2407 ExecRuntime
**ret
) {
2408 _cleanup_close_pair_
int ephemeral_storage_socket
[2] = EBADF_PAIR
;
2409 _cleanup_free_
char *ephemeral
= NULL
;
2410 _cleanup_(exec_runtime_freep
) ExecRuntime
*rt
= NULL
;
2417 if (!shared
&& !creds
&& !exec_needs_ephemeral(context
)) {
2422 if (exec_needs_ephemeral(context
)) {
2423 r
= mkdir_p("/var/lib/systemd/ephemeral-trees", 0755);
2427 r
= tempfn_random_child("/var/lib/systemd/ephemeral-trees", unit
->id
, &ephemeral
);
2431 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, ephemeral_storage_socket
) < 0)
2435 rt
= new(ExecRuntime
, 1);
2439 *rt
= (ExecRuntime
) {
2441 .dynamic_creds
= creds
,
2442 .ephemeral_copy
= TAKE_PTR(ephemeral
),
2443 .ephemeral_storage_socket
[0] = TAKE_FD(ephemeral_storage_socket
[0]),
2444 .ephemeral_storage_socket
[1] = TAKE_FD(ephemeral_storage_socket
[1]),
2447 *ret
= TAKE_PTR(rt
);
2451 ExecRuntime
* exec_runtime_free(ExecRuntime
*rt
) {
2455 exec_shared_runtime_unref(rt
->shared
);
2456 dynamic_creds_unref(rt
->dynamic_creds
);
2458 rt
->ephemeral_copy
= destroy_tree(rt
->ephemeral_copy
);
2460 safe_close_pair(rt
->ephemeral_storage_socket
);
2464 ExecRuntime
* exec_runtime_destroy(ExecRuntime
*rt
) {
2468 rt
->shared
= exec_shared_runtime_destroy(rt
->shared
);
2469 rt
->dynamic_creds
= dynamic_creds_destroy(rt
->dynamic_creds
);
2470 return exec_runtime_free(rt
);
2473 void exec_runtime_clear(ExecRuntime
*rt
) {
2477 safe_close_pair(rt
->ephemeral_storage_socket
);
2478 rt
->ephemeral_copy
= mfree(rt
->ephemeral_copy
);
2481 void exec_params_shallow_clear(ExecParameters
*p
) {
2485 /* This is called on the PID1 side, as many of the struct's FDs are only borrowed, and actually
2486 * owned by the manager or other objects, and reused across multiple units. */
2488 p
->environment
= strv_free(p
->environment
);
2489 p
->fd_names
= strv_free(p
->fd_names
);
2490 p
->files_env
= strv_free(p
->files_env
);
2491 p
->fds
= mfree(p
->fds
);
2492 p
->exec_fd
= safe_close(p
->exec_fd
);
2493 p
->user_lookup_fd
= -EBADF
;
2494 p
->bpf_outer_map_fd
= -EBADF
;
2495 p
->unit_id
= mfree(p
->unit_id
);
2496 p
->invocation_id
= SD_ID128_NULL
;
2497 p
->invocation_id_string
[0] = '\0';
2498 p
->confirm_spawn
= mfree(p
->confirm_spawn
);
2501 void exec_params_deep_clear(ExecParameters
*p
) {
2505 /* This is called on the sd-executor side, where everything received is owned by the process and has
2506 * to be fully cleaned up to make sanitizers and analyzers happy, as opposed as the shallow clean
2507 * function above. */
2509 close_many_unset(p
->fds
, p
->n_socket_fds
+ p
->n_storage_fds
);
2511 p
->cgroup_path
= mfree(p
->cgroup_path
);
2514 free_many_charp(p
->prefix
, _EXEC_DIRECTORY_TYPE_MAX
);
2515 p
->prefix
= mfree(p
->prefix
);
2518 p
->received_credentials_directory
= mfree(p
->received_credentials_directory
);
2519 p
->received_encrypted_credentials_directory
= mfree(p
->received_encrypted_credentials_directory
);
2522 close_many_and_free(p
->idle_pipe
, 4);
2523 p
->idle_pipe
= NULL
;
2526 p
->stdin_fd
= safe_close(p
->stdin_fd
);
2527 p
->stdout_fd
= safe_close(p
->stdout_fd
);
2528 p
->stderr_fd
= safe_close(p
->stderr_fd
);
2530 p
->notify_socket
= mfree(p
->notify_socket
);
2532 open_file_free_many(&p
->open_files
);
2534 p
->fallback_smack_process_label
= mfree(p
->fallback_smack_process_label
);
2536 exec_params_shallow_clear(p
);
2539 void exec_directory_done(ExecDirectory
*d
) {
2543 FOREACH_ARRAY(i
, d
->items
, d
->n_items
) {
2545 strv_free(i
->symlinks
);
2548 d
->items
= mfree(d
->items
);
2553 static ExecDirectoryItem
*exec_directory_find(ExecDirectory
*d
, const char *path
) {
2557 FOREACH_ARRAY(i
, d
->items
, d
->n_items
)
2558 if (path_equal(i
->path
, path
))
2564 int exec_directory_add(ExecDirectory
*d
, const char *path
, const char *symlink
) {
2565 _cleanup_strv_free_
char **s
= NULL
;
2566 _cleanup_free_
char *p
= NULL
;
2567 ExecDirectoryItem
*existing
;
2573 existing
= exec_directory_find(d
, path
);
2575 r
= strv_extend(&existing
->symlinks
, symlink
);
2579 return 0; /* existing item is updated */
2587 s
= strv_new(symlink
);
2592 if (!GREEDY_REALLOC(d
->items
, d
->n_items
+ 1))
2595 d
->items
[d
->n_items
++] = (ExecDirectoryItem
) {
2596 .path
= TAKE_PTR(p
),
2597 .symlinks
= TAKE_PTR(s
),
2600 return 1; /* new item is added */
2603 static int exec_directory_item_compare_func(const ExecDirectoryItem
*a
, const ExecDirectoryItem
*b
) {
2607 return path_compare(a
->path
, b
->path
);
2610 void exec_directory_sort(ExecDirectory
*d
) {
2613 /* Sort the exec directories to make always parent directories processed at first in
2614 * setup_exec_directory(), e.g., even if StateDirectory=foo/bar foo, we need to create foo at first,
2615 * then foo/bar. Also, set .only_create flag if one of the parent directories is contained in the
2616 * list. See also comments in setup_exec_directory() and issue #24783. */
2618 if (d
->n_items
<= 1)
2621 typesafe_qsort(d
->items
, d
->n_items
, exec_directory_item_compare_func
);
2623 for (size_t i
= 1; i
< d
->n_items
; i
++)
2624 for (size_t j
= 0; j
< i
; j
++)
2625 if (path_startswith(d
->items
[i
].path
, d
->items
[j
].path
)) {
2626 d
->items
[i
].only_create
= true;
2631 ExecCleanMask
exec_clean_mask_from_string(const char *s
) {
2632 ExecDirectoryType t
;
2636 if (streq(s
, "all"))
2637 return EXEC_CLEAN_ALL
;
2638 if (streq(s
, "fdstore"))
2639 return EXEC_CLEAN_FDSTORE
;
2641 t
= exec_resource_type_from_string(s
);
2643 return (ExecCleanMask
) t
;
2648 static const char* const exec_input_table
[_EXEC_INPUT_MAX
] = {
2649 [EXEC_INPUT_NULL
] = "null",
2650 [EXEC_INPUT_TTY
] = "tty",
2651 [EXEC_INPUT_TTY_FORCE
] = "tty-force",
2652 [EXEC_INPUT_TTY_FAIL
] = "tty-fail",
2653 [EXEC_INPUT_SOCKET
] = "socket",
2654 [EXEC_INPUT_NAMED_FD
] = "fd",
2655 [EXEC_INPUT_DATA
] = "data",
2656 [EXEC_INPUT_FILE
] = "file",
2659 DEFINE_STRING_TABLE_LOOKUP(exec_input
, ExecInput
);
2661 static const char* const exec_output_table
[_EXEC_OUTPUT_MAX
] = {
2662 [EXEC_OUTPUT_INHERIT
] = "inherit",
2663 [EXEC_OUTPUT_NULL
] = "null",
2664 [EXEC_OUTPUT_TTY
] = "tty",
2665 [EXEC_OUTPUT_KMSG
] = "kmsg",
2666 [EXEC_OUTPUT_KMSG_AND_CONSOLE
] = "kmsg+console",
2667 [EXEC_OUTPUT_JOURNAL
] = "journal",
2668 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE
] = "journal+console",
2669 [EXEC_OUTPUT_SOCKET
] = "socket",
2670 [EXEC_OUTPUT_NAMED_FD
] = "fd",
2671 [EXEC_OUTPUT_FILE
] = "file",
2672 [EXEC_OUTPUT_FILE_APPEND
] = "append",
2673 [EXEC_OUTPUT_FILE_TRUNCATE
] = "truncate",
2676 DEFINE_STRING_TABLE_LOOKUP(exec_output
, ExecOutput
);
2678 static const char* const exec_utmp_mode_table
[_EXEC_UTMP_MODE_MAX
] = {
2679 [EXEC_UTMP_INIT
] = "init",
2680 [EXEC_UTMP_LOGIN
] = "login",
2681 [EXEC_UTMP_USER
] = "user",
2684 DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode
, ExecUtmpMode
);
2686 static const char* const exec_preserve_mode_table
[_EXEC_PRESERVE_MODE_MAX
] = {
2687 [EXEC_PRESERVE_NO
] = "no",
2688 [EXEC_PRESERVE_YES
] = "yes",
2689 [EXEC_PRESERVE_RESTART
] = "restart",
2692 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode
, ExecPreserveMode
, EXEC_PRESERVE_YES
);
2694 /* This table maps ExecDirectoryType to the setting it is configured with in the unit */
2695 static const char* const exec_directory_type_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2696 [EXEC_DIRECTORY_RUNTIME
] = "RuntimeDirectory",
2697 [EXEC_DIRECTORY_STATE
] = "StateDirectory",
2698 [EXEC_DIRECTORY_CACHE
] = "CacheDirectory",
2699 [EXEC_DIRECTORY_LOGS
] = "LogsDirectory",
2700 [EXEC_DIRECTORY_CONFIGURATION
] = "ConfigurationDirectory",
2703 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type
, ExecDirectoryType
);
2705 /* This table maps ExecDirectoryType to the symlink setting it is configured with in the unit */
2706 static const char* const exec_directory_type_symlink_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2707 [EXEC_DIRECTORY_RUNTIME
] = "RuntimeDirectorySymlink",
2708 [EXEC_DIRECTORY_STATE
] = "StateDirectorySymlink",
2709 [EXEC_DIRECTORY_CACHE
] = "CacheDirectorySymlink",
2710 [EXEC_DIRECTORY_LOGS
] = "LogsDirectorySymlink",
2711 [EXEC_DIRECTORY_CONFIGURATION
] = "ConfigurationDirectorySymlink",
2714 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type_symlink
, ExecDirectoryType
);
2716 static const char* const exec_directory_type_mode_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2717 [EXEC_DIRECTORY_RUNTIME
] = "RuntimeDirectoryMode",
2718 [EXEC_DIRECTORY_STATE
] = "StateDirectoryMode",
2719 [EXEC_DIRECTORY_CACHE
] = "CacheDirectoryMode",
2720 [EXEC_DIRECTORY_LOGS
] = "LogsDirectoryMode",
2721 [EXEC_DIRECTORY_CONFIGURATION
] = "ConfigurationDirectoryMode",
2724 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type_mode
, ExecDirectoryType
);
2726 /* And this table maps ExecDirectoryType too, but to a generic term identifying the type of resource. This
2727 * one is supposed to be generic enough to be used for unit types that don't use ExecContext and per-unit
2728 * directories, specifically .timer units with their timestamp touch file. */
2729 static const char* const exec_resource_type_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2730 [EXEC_DIRECTORY_RUNTIME
] = "runtime",
2731 [EXEC_DIRECTORY_STATE
] = "state",
2732 [EXEC_DIRECTORY_CACHE
] = "cache",
2733 [EXEC_DIRECTORY_LOGS
] = "logs",
2734 [EXEC_DIRECTORY_CONFIGURATION
] = "configuration",
2737 DEFINE_STRING_TABLE_LOOKUP(exec_resource_type
, ExecDirectoryType
);
2739 static const char* const exec_keyring_mode_table
[_EXEC_KEYRING_MODE_MAX
] = {
2740 [EXEC_KEYRING_INHERIT
] = "inherit",
2741 [EXEC_KEYRING_PRIVATE
] = "private",
2742 [EXEC_KEYRING_SHARED
] = "shared",
2745 DEFINE_STRING_TABLE_LOOKUP(exec_keyring_mode
, ExecKeyringMode
);