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 const char *exec_context_tty_path(const ExecContext
*context
) {
79 if (context
->stdio_as_fds
)
82 if (context
->tty_path
)
83 return context
->tty_path
;
85 return "/dev/console";
88 int exec_context_tty_size(const ExecContext
*context
, unsigned *ret_rows
, unsigned *ret_cols
) {
96 rows
= context
->tty_rows
;
97 cols
= context
->tty_cols
;
99 tty
= exec_context_tty_path(context
);
101 (void) proc_cmdline_tty_size(tty
, rows
== UINT_MAX
? &rows
: NULL
, cols
== UINT_MAX
? &cols
: NULL
);
109 void exec_context_tty_reset(const ExecContext
*context
, const ExecParameters
*p
) {
110 _cleanup_close_
int _fd
= -EBADF
, lock_fd
= -EBADF
;
111 const char *path
= exec_context_tty_path(ASSERT_PTR(context
));
114 if (p
&& p
->stdin_fd
>= 0)
117 fd
= _fd
= open_terminal(path
, O_RDWR
|O_NOCTTY
|O_CLOEXEC
|O_NONBLOCK
);
121 return; /* nothing to do */
123 /* Take a synchronization lock for the duration of the setup that we do here.
124 * systemd-vconsole-setup.service also takes the lock to avoid being interrupted.
125 * We open a new fd that will be closed automatically, and operate on it for convenience.
127 lock_fd
= lock_dev_console();
129 return (void) log_debug_errno(lock_fd
,
130 "Failed to lock /dev/console: %m");
132 if (context
->tty_vhangup
)
133 (void) terminal_vhangup_fd(fd
);
135 if (context
->tty_reset
)
136 (void) reset_terminal_fd(fd
, true);
138 if (p
&& p
->stdin_fd
>= 0) {
139 unsigned rows
= context
->tty_rows
, cols
= context
->tty_cols
;
141 (void) exec_context_tty_size(context
, &rows
, &cols
);
142 (void) terminal_set_size_fd(p
->stdin_fd
, path
, rows
, cols
);
145 if (context
->tty_vt_disallocate
&& path
)
146 (void) vt_disallocate(path
);
149 static bool is_terminal_input(ExecInput i
) {
152 EXEC_INPUT_TTY_FORCE
,
153 EXEC_INPUT_TTY_FAIL
);
156 static bool is_terminal_output(ExecOutput o
) {
159 EXEC_OUTPUT_KMSG_AND_CONSOLE
,
160 EXEC_OUTPUT_JOURNAL_AND_CONSOLE
);
163 bool exec_needs_network_namespace(const ExecContext
*context
) {
166 return context
->private_network
|| context
->network_namespace_path
;
169 static bool exec_needs_ephemeral(const ExecContext
*context
) {
170 return (context
->root_image
|| context
->root_directory
) && context
->root_ephemeral
;
173 bool exec_needs_ipc_namespace(const ExecContext
*context
) {
176 return context
->private_ipc
|| context
->ipc_namespace_path
;
179 bool exec_needs_mount_namespace(
180 const ExecContext
*context
,
181 const ExecParameters
*params
,
182 const ExecRuntime
*runtime
) {
186 if (context
->root_image
)
189 if (!strv_isempty(context
->read_write_paths
) ||
190 !strv_isempty(context
->read_only_paths
) ||
191 !strv_isempty(context
->inaccessible_paths
) ||
192 !strv_isempty(context
->exec_paths
) ||
193 !strv_isempty(context
->no_exec_paths
))
196 if (context
->n_bind_mounts
> 0)
199 if (context
->n_temporary_filesystems
> 0)
202 if (context
->n_mount_images
> 0)
205 if (context
->n_extension_images
> 0)
208 if (!strv_isempty(context
->extension_directories
))
211 if (!IN_SET(context
->mount_propagation_flag
, 0, MS_SHARED
))
214 if (context
->private_tmp
&& runtime
&& runtime
->shared
&& (runtime
->shared
->tmp_dir
|| runtime
->shared
->var_tmp_dir
))
217 if (context
->private_devices
||
218 context
->private_mounts
> 0 ||
219 (context
->private_mounts
< 0 && exec_needs_network_namespace(context
)) ||
220 context
->protect_system
!= PROTECT_SYSTEM_NO
||
221 context
->protect_home
!= PROTECT_HOME_NO
||
222 context
->protect_kernel_tunables
||
223 context
->protect_kernel_modules
||
224 context
->protect_kernel_logs
||
225 context
->protect_control_groups
||
226 context
->protect_proc
!= PROTECT_PROC_DEFAULT
||
227 context
->proc_subset
!= PROC_SUBSET_ALL
||
228 exec_needs_ipc_namespace(context
))
231 if (context
->root_directory
) {
232 if (exec_context_get_effective_mount_apivfs(context
))
235 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++) {
236 if (params
&& !params
->prefix
[t
])
239 if (context
->directories
[t
].n_items
> 0)
244 if (context
->dynamic_user
&&
245 (context
->directories
[EXEC_DIRECTORY_STATE
].n_items
> 0 ||
246 context
->directories
[EXEC_DIRECTORY_CACHE
].n_items
> 0 ||
247 context
->directories
[EXEC_DIRECTORY_LOGS
].n_items
> 0))
250 if (context
->log_namespace
)
256 bool exec_directory_is_private(const ExecContext
*context
, ExecDirectoryType type
) {
259 if (!context
->dynamic_user
)
262 if (type
== EXEC_DIRECTORY_CONFIGURATION
)
265 if (type
== EXEC_DIRECTORY_RUNTIME
&& context
->runtime_directory_preserve_mode
== EXEC_PRESERVE_NO
)
271 int exec_params_get_cgroup_path(
272 const ExecParameters
*params
,
273 const CGroupContext
*c
,
276 const char *subgroup
= NULL
;
282 if (!params
->cgroup_path
)
285 /* If we are called for a unit where cgroup delegation is on, and the payload created its own populated
286 * subcgroup (which we expect it to do, after all it asked for delegation), then we cannot place the control
287 * processes started after the main unit's process in the unit's main cgroup because it is now an inner one,
288 * and inner cgroups may not contain processes. Hence, if delegation is on, and this is a control process,
289 * let's use ".control" as subcgroup instead. Note that we do so only for ExecStartPost=, ExecReload=,
290 * ExecStop=, ExecStopPost=, i.e. for the commands where the main process is already forked. For ExecStartPre=
291 * this is not necessary, the cgroup is still empty. We distinguish these cases with the EXEC_CONTROL_CGROUP
292 * flag, which is only passed for the former statements, not for the latter. */
294 if (FLAGS_SET(params
->flags
, EXEC_CGROUP_DELEGATE
) && (FLAGS_SET(params
->flags
, EXEC_CONTROL_CGROUP
) || c
->delegate_subgroup
)) {
295 if (FLAGS_SET(params
->flags
, EXEC_IS_CONTROL
))
296 subgroup
= ".control";
298 subgroup
= c
->delegate_subgroup
;
302 p
= path_join(params
->cgroup_path
, subgroup
);
304 p
= strdup(params
->cgroup_path
);
312 bool exec_context_get_cpu_affinity_from_numa(const ExecContext
*c
) {
315 return c
->cpu_affinity_from_numa
;
318 static void log_command_line(Unit
*unit
, const char *msg
, const char *executable
, char **argv
) {
326 _cleanup_free_
char *cmdline
= quote_command_line(argv
, SHELL_ESCAPE_EMPTY
);
328 log_unit_struct(unit
, LOG_DEBUG
,
329 "EXECUTABLE=%s", executable
,
330 LOG_UNIT_MESSAGE(unit
, "%s: %s", msg
, strnull(cmdline
)),
331 LOG_UNIT_INVOCATION_ID(unit
));
334 static int exec_context_load_environment(const Unit
*unit
, const ExecContext
*c
, char ***l
);
336 int exec_spawn(Unit
*unit
,
337 ExecCommand
*command
,
338 const ExecContext
*context
,
339 ExecParameters
*params
,
340 ExecRuntime
*runtime
,
341 const CGroupContext
*cgroup_context
,
344 char serialization_fd_number
[DECIMAL_STR_MAX(int) + 1];
345 _cleanup_free_
char *subcgroup_path
= NULL
, *log_level
= NULL
, *executor_path
= NULL
;
346 _cleanup_fdset_free_ FDSet
*fdset
= NULL
;
347 _cleanup_fclose_
FILE *f
= NULL
;
352 assert(unit
->manager
);
353 assert(unit
->manager
->executor_fd
>= 0);
358 assert(params
->fds
|| (params
->n_socket_fds
+ params
->n_storage_fds
<= 0));
359 assert(!params
->files_env
); /* We fill this field, ensure it comes NULL-initialized to us */
361 LOG_CONTEXT_PUSH_UNIT(unit
);
363 r
= exec_context_load_environment(unit
, context
, ¶ms
->files_env
);
365 return log_unit_error_errno(unit
, r
, "Failed to load environment files: %m");
367 /* Fork with up-to-date SELinux label database, so the child inherits the up-to-date db
368 and, until the next SELinux policy changes, we save further reloads in future children. */
369 mac_selinux_maybe_reload();
371 /* We won't know the real executable path until we create the mount namespace in the child, but we
372 want to log from the parent, so we use the possibly inaccurate path here. */
373 log_command_line(unit
, "About to execute", command
->path
, command
->argv
);
375 if (params
->cgroup_path
) {
376 r
= exec_params_get_cgroup_path(params
, cgroup_context
, &subcgroup_path
);
378 return log_unit_error_errno(unit
, r
, "Failed to acquire subcgroup path: %m");
380 /* If there's a subcgroup, then let's create it here now (the main cgroup was already
381 * realized by the unit logic) */
383 r
= cg_create(SYSTEMD_CGROUP_CONTROLLER
, subcgroup_path
);
385 return log_unit_error_errno(unit
, r
, "Failed to create subcgroup '%s': %m", subcgroup_path
);
389 /* In order to avoid copy-on-write traps and OOM-kills when pid1's memory.current is above the
390 * child's memory.max, serialize all the state needed to start the unit, and pass it to the
391 * systemd-executor binary. clone() with CLONE_VM + CLONE_VFORK will pause the parent until the exec
392 * and ensure all memory is shared. The child immediately execs the new binary so the delay should
393 * be minimal. Once glibc provides a clone3 wrapper we can switch to that, and clone directly in the
396 r
= open_serialization_file("sd-executor-state", &f
);
398 return log_unit_error_errno(unit
, r
, "Failed to open serialization stream: %m");
404 r
= exec_serialize_invocation(f
, fdset
, context
, command
, params
, runtime
, cgroup_context
);
406 return log_unit_error_errno(unit
, r
, "Failed to serialize parameters: %m");
408 if (fseeko(f
, 0, SEEK_SET
) == (off_t
) -1)
409 return log_unit_error_errno(unit
, errno
, "Failed to reseek on serialization stream: %m");
411 r
= fd_cloexec(fileno(f
), false);
413 return log_unit_error_errno(unit
, r
, "Failed to set O_CLOEXEC on serialization fd: %m");
415 r
= fdset_cloexec(fdset
, false);
417 return log_unit_error_errno(unit
, r
, "Failed to set O_CLOEXEC on serialized fds: %m");
419 r
= log_level_to_string_alloc(log_get_max_level(), &log_level
);
421 return log_unit_error_errno(unit
, r
, "Failed to convert log level to string: %m");
423 r
= fd_get_path(unit
->manager
->executor_fd
, &executor_path
);
425 return log_unit_error_errno(unit
, r
, "Failed to get executor path from fd: %m");
427 xsprintf(serialization_fd_number
, "%i", fileno(f
));
429 /* The executor binary is pinned, to avoid compatibility problems during upgrades. */
430 r
= posix_spawn_wrapper(
431 FORMAT_PROC_FD_PATH(unit
->manager
->executor_fd
),
432 STRV_MAKE(executor_path
,
433 "--deserialize", serialization_fd_number
,
434 "--log-level", log_level
,
435 "--log-target", log_target_to_string(manager_get_executor_log_target(unit
->manager
))),
439 return log_unit_error_errno(unit
, r
, "Failed to spawn executor: %m");
441 log_unit_debug(unit
, "Forked %s as "PID_FMT
, command
->path
, pid
);
443 /* We add the new process to the cgroup both in the child (so that we can be sure that no user code is ever
444 * executed outside of the cgroup) and in the parent (so that we can be sure that when we kill the cgroup the
445 * process will be killed too). */
447 (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER
, subcgroup_path
, pid
);
449 exec_status_start(&command
->exec_status
, pid
);
455 void exec_context_init(ExecContext
*c
) {
458 /* When initializing a bool member to 'true', make sure to serialize in execute-serialize.c using
459 * serialize_bool() instead of serialize_bool_elide(). */
463 .ioprio
= IOPRIO_DEFAULT_CLASS_AND_PRIO
,
464 .cpu_sched_policy
= SCHED_OTHER
,
465 .syslog_priority
= LOG_DAEMON
|LOG_INFO
,
466 .syslog_level_prefix
= true,
467 .ignore_sigpipe
= true,
468 .timer_slack_nsec
= NSEC_INFINITY
,
469 .personality
= PERSONALITY_INVALID
,
470 .timeout_clean_usec
= USEC_INFINITY
,
471 .capability_bounding_set
= CAP_MASK_UNSET
,
472 .restrict_namespaces
= NAMESPACE_FLAGS_INITIAL
,
475 .syscall_errno
= SECCOMP_ERROR_NUMBER_KILL
,
477 .tty_rows
= UINT_MAX
,
478 .tty_cols
= UINT_MAX
,
479 .private_mounts
= -1,
481 .set_login_environment
= -1,
484 FOREACH_ARRAY(d
, c
->directories
, _EXEC_DIRECTORY_TYPE_MAX
)
487 numa_policy_reset(&c
->numa_policy
);
489 assert_cc(NAMESPACE_FLAGS_INITIAL
!= NAMESPACE_FLAGS_ALL
);
492 void exec_context_done(ExecContext
*c
) {
495 c
->environment
= strv_free(c
->environment
);
496 c
->environment_files
= strv_free(c
->environment_files
);
497 c
->pass_environment
= strv_free(c
->pass_environment
);
498 c
->unset_environment
= strv_free(c
->unset_environment
);
500 rlimit_free_all(c
->rlimit
);
502 for (size_t l
= 0; l
< 3; l
++) {
503 c
->stdio_fdname
[l
] = mfree(c
->stdio_fdname
[l
]);
504 c
->stdio_file
[l
] = mfree(c
->stdio_file
[l
]);
507 c
->working_directory
= mfree(c
->working_directory
);
508 c
->root_directory
= mfree(c
->root_directory
);
509 c
->root_image
= mfree(c
->root_image
);
510 c
->root_image_options
= mount_options_free_all(c
->root_image_options
);
511 c
->root_hash
= mfree(c
->root_hash
);
512 c
->root_hash_size
= 0;
513 c
->root_hash_path
= mfree(c
->root_hash_path
);
514 c
->root_hash_sig
= mfree(c
->root_hash_sig
);
515 c
->root_hash_sig_size
= 0;
516 c
->root_hash_sig_path
= mfree(c
->root_hash_sig_path
);
517 c
->root_verity
= mfree(c
->root_verity
);
518 c
->extension_images
= mount_image_free_many(c
->extension_images
, &c
->n_extension_images
);
519 c
->extension_directories
= strv_free(c
->extension_directories
);
520 c
->tty_path
= mfree(c
->tty_path
);
521 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
522 c
->user
= mfree(c
->user
);
523 c
->group
= mfree(c
->group
);
525 c
->supplementary_groups
= strv_free(c
->supplementary_groups
);
527 c
->pam_name
= mfree(c
->pam_name
);
529 c
->read_only_paths
= strv_free(c
->read_only_paths
);
530 c
->read_write_paths
= strv_free(c
->read_write_paths
);
531 c
->inaccessible_paths
= strv_free(c
->inaccessible_paths
);
532 c
->exec_paths
= strv_free(c
->exec_paths
);
533 c
->no_exec_paths
= strv_free(c
->no_exec_paths
);
534 c
->exec_search_path
= strv_free(c
->exec_search_path
);
536 bind_mount_free_many(c
->bind_mounts
, c
->n_bind_mounts
);
537 c
->bind_mounts
= NULL
;
538 c
->n_bind_mounts
= 0;
539 temporary_filesystem_free_many(c
->temporary_filesystems
, c
->n_temporary_filesystems
);
540 c
->temporary_filesystems
= NULL
;
541 c
->n_temporary_filesystems
= 0;
542 c
->mount_images
= mount_image_free_many(c
->mount_images
, &c
->n_mount_images
);
544 cpu_set_reset(&c
->cpu_set
);
545 numa_policy_reset(&c
->numa_policy
);
547 c
->utmp_id
= mfree(c
->utmp_id
);
548 c
->selinux_context
= mfree(c
->selinux_context
);
549 c
->apparmor_profile
= mfree(c
->apparmor_profile
);
550 c
->smack_process_label
= mfree(c
->smack_process_label
);
552 c
->restrict_filesystems
= set_free_free(c
->restrict_filesystems
);
554 c
->syscall_filter
= hashmap_free(c
->syscall_filter
);
555 c
->syscall_archs
= set_free(c
->syscall_archs
);
556 c
->address_families
= set_free(c
->address_families
);
558 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++)
559 exec_directory_done(&c
->directories
[t
]);
561 c
->log_level_max
= -1;
563 exec_context_free_log_extra_fields(c
);
564 c
->log_filter_allowed_patterns
= set_free_free(c
->log_filter_allowed_patterns
);
565 c
->log_filter_denied_patterns
= set_free_free(c
->log_filter_denied_patterns
);
567 c
->log_ratelimit_interval_usec
= 0;
568 c
->log_ratelimit_burst
= 0;
570 c
->stdin_data
= mfree(c
->stdin_data
);
571 c
->stdin_data_size
= 0;
573 c
->network_namespace_path
= mfree(c
->network_namespace_path
);
574 c
->ipc_namespace_path
= mfree(c
->ipc_namespace_path
);
576 c
->log_namespace
= mfree(c
->log_namespace
);
578 c
->load_credentials
= hashmap_free(c
->load_credentials
);
579 c
->set_credentials
= hashmap_free(c
->set_credentials
);
580 c
->import_credentials
= set_free_free(c
->import_credentials
);
582 c
->root_image_policy
= image_policy_free(c
->root_image_policy
);
583 c
->mount_image_policy
= image_policy_free(c
->mount_image_policy
);
584 c
->extension_image_policy
= image_policy_free(c
->extension_image_policy
);
587 int exec_context_destroy_runtime_directory(const ExecContext
*c
, const char *runtime_prefix
) {
593 FOREACH_ARRAY(i
, c
->directories
[EXEC_DIRECTORY_RUNTIME
].items
, c
->directories
[EXEC_DIRECTORY_RUNTIME
].n_items
) {
594 _cleanup_free_
char *p
= NULL
;
596 if (exec_directory_is_private(c
, EXEC_DIRECTORY_RUNTIME
))
597 p
= path_join(runtime_prefix
, "private", i
->path
);
599 p
= path_join(runtime_prefix
, i
->path
);
603 /* We execute this synchronously, since we need to be sure this is gone when we start the
605 (void) rm_rf(p
, REMOVE_ROOT
);
607 STRV_FOREACH(symlink
, i
->symlinks
) {
608 _cleanup_free_
char *symlink_abs
= NULL
;
610 if (exec_directory_is_private(c
, EXEC_DIRECTORY_RUNTIME
))
611 symlink_abs
= path_join(runtime_prefix
, "private", *symlink
);
613 symlink_abs
= path_join(runtime_prefix
, *symlink
);
617 (void) unlink(symlink_abs
);
624 int exec_context_destroy_mount_ns_dir(Unit
*u
) {
625 _cleanup_free_
char *p
= NULL
;
627 if (!u
|| !MANAGER_IS_SYSTEM(u
->manager
))
630 p
= path_join("/run/systemd/propagate/", u
->id
);
634 /* This is only filled transiently (see mount_in_namespace()), should be empty or even non-existent*/
635 if (rmdir(p
) < 0 && errno
!= ENOENT
)
636 log_unit_debug_errno(u
, errno
, "Unable to remove propagation dir '%s', ignoring: %m", p
);
641 void exec_command_done(ExecCommand
*c
) {
644 c
->path
= mfree(c
->path
);
645 c
->argv
= strv_free(c
->argv
);
648 void exec_command_done_array(ExecCommand
*c
, size_t n
) {
649 FOREACH_ARRAY(i
, c
, n
)
650 exec_command_done(i
);
653 ExecCommand
* exec_command_free_list(ExecCommand
*c
) {
656 while ((i
= LIST_POP(command
, c
))) {
657 exec_command_done(i
);
664 void exec_command_free_array(ExecCommand
**c
, size_t n
) {
665 FOREACH_ARRAY(i
, c
, n
)
666 *i
= exec_command_free_list(*i
);
669 void exec_command_reset_status_array(ExecCommand
*c
, size_t n
) {
670 FOREACH_ARRAY(i
, c
, n
)
671 exec_status_reset(&i
->exec_status
);
674 void exec_command_reset_status_list_array(ExecCommand
**c
, size_t n
) {
675 FOREACH_ARRAY(i
, c
, n
)
676 LIST_FOREACH(command
, z
, *i
)
677 exec_status_reset(&z
->exec_status
);
680 typedef struct InvalidEnvInfo
{
685 static void invalid_env(const char *p
, void *userdata
) {
686 InvalidEnvInfo
*info
= userdata
;
688 log_unit_error(info
->unit
, "Ignoring invalid environment assignment '%s': %s", p
, info
->path
);
691 const char* exec_context_fdname(const ExecContext
*c
, int fd_index
) {
697 if (c
->std_input
!= EXEC_INPUT_NAMED_FD
)
700 return c
->stdio_fdname
[STDIN_FILENO
] ?: "stdin";
703 if (c
->std_output
!= EXEC_OUTPUT_NAMED_FD
)
706 return c
->stdio_fdname
[STDOUT_FILENO
] ?: "stdout";
709 if (c
->std_error
!= EXEC_OUTPUT_NAMED_FD
)
712 return c
->stdio_fdname
[STDERR_FILENO
] ?: "stderr";
719 static int exec_context_load_environment(const Unit
*unit
, const ExecContext
*c
, char ***ret
) {
720 _cleanup_strv_free_
char **v
= NULL
;
726 STRV_FOREACH(i
, c
->environment_files
) {
727 _cleanup_globfree_ glob_t pglob
= {};
736 if (!path_is_absolute(fn
)) {
742 /* Filename supports globbing, take all matching files */
743 r
= safe_glob(fn
, 0, &pglob
);
750 /* When we don't match anything, -ENOENT should be returned */
751 assert(pglob
.gl_pathc
> 0);
753 FOREACH_ARRAY(path
, pglob
.gl_pathv
, pglob
.gl_pathc
) {
754 _cleanup_strv_free_
char **p
= NULL
;
756 r
= load_env_file(NULL
, *path
, &p
);
763 /* Log invalid environment variables with filename */
765 InvalidEnvInfo info
= {
770 p
= strv_env_clean_with_callback(p
, invalid_env
, &info
);
776 char **m
= strv_env_merge(v
, p
);
780 strv_free_and_replace(v
, m
);
790 static bool tty_may_match_dev_console(const char *tty
) {
791 _cleanup_free_
char *resolved
= NULL
;
796 tty
= skip_dev_prefix(tty
);
798 /* trivial identity? */
799 if (streq(tty
, "console"))
802 if (resolve_dev_console(&resolved
) < 0)
803 return true; /* if we could not resolve, assume it may */
805 /* "tty0" means the active VC, so it may be the same sometimes */
806 return path_equal(resolved
, tty
) || (streq(resolved
, "tty0") && tty_is_vc(tty
));
809 static bool exec_context_may_touch_tty(const ExecContext
*ec
) {
812 return ec
->tty_reset
||
814 ec
->tty_vt_disallocate
||
815 is_terminal_input(ec
->std_input
) ||
816 is_terminal_output(ec
->std_output
) ||
817 is_terminal_output(ec
->std_error
);
820 bool exec_context_may_touch_console(const ExecContext
*ec
) {
822 return exec_context_may_touch_tty(ec
) &&
823 tty_may_match_dev_console(exec_context_tty_path(ec
));
826 static void strv_fprintf(FILE *f
, char **l
) {
830 fprintf(f
, " %s", *g
);
833 static void strv_dump(FILE* f
, const char *prefix
, const char *name
, char **strv
) {
838 if (!strv_isempty(strv
)) {
839 fprintf(f
, "%s%s:", prefix
, name
);
840 strv_fprintf(f
, strv
);
845 void exec_params_dump(const ExecParameters
*p
, FILE* f
, const char *prefix
) {
849 prefix
= strempty(prefix
);
852 "%sRuntimeScope: %s\n"
854 "%sSELinuxContextNetwork: %s\n"
855 "%sCgroupSupportedMask: %u\n"
857 "%sCrededentialsDirectory: %s\n"
858 "%sEncryptedCredentialsDirectory: %s\n"
859 "%sConfirmSpawn: %s\n"
860 "%sShallConfirmSpawn: %s\n"
861 "%sWatchdogUSec: " USEC_FMT
"\n"
862 "%sNotifySocket: %s\n"
863 "%sFallbackSmackProcessLabel: %s\n",
864 prefix
, runtime_scope_to_string(p
->runtime_scope
),
866 prefix
, yes_no(p
->selinux_context_net
),
867 prefix
, p
->cgroup_supported
,
868 prefix
, p
->cgroup_path
,
869 prefix
, strempty(p
->received_credentials_directory
),
870 prefix
, strempty(p
->received_encrypted_credentials_directory
),
871 prefix
, strempty(p
->confirm_spawn
),
872 prefix
, yes_no(p
->shall_confirm_spawn
),
873 prefix
, p
->watchdog_usec
,
874 prefix
, strempty(p
->notify_socket
),
875 prefix
, strempty(p
->fallback_smack_process_label
));
877 strv_dump(f
, prefix
, "FdNames", p
->fd_names
);
878 strv_dump(f
, prefix
, "Environment", p
->environment
);
879 strv_dump(f
, prefix
, "Prefix", p
->prefix
);
881 LIST_FOREACH(open_files
, file
, p
->open_files
)
882 fprintf(f
, "%sOpenFile: %s %s", prefix
, file
->path
, open_file_flags_to_string(file
->flags
));
884 strv_dump(f
, prefix
, "FilesEnv", p
->files_env
);
887 void exec_context_dump(const ExecContext
*c
, FILE* f
, const char *prefix
) {
893 prefix
= strempty(prefix
);
897 "%sWorkingDirectory: %s\n"
898 "%sRootDirectory: %s\n"
899 "%sRootEphemeral: %s\n"
900 "%sNonBlocking: %s\n"
902 "%sPrivateDevices: %s\n"
903 "%sProtectKernelTunables: %s\n"
904 "%sProtectKernelModules: %s\n"
905 "%sProtectKernelLogs: %s\n"
906 "%sProtectClock: %s\n"
907 "%sProtectControlGroups: %s\n"
908 "%sPrivateNetwork: %s\n"
909 "%sPrivateUsers: %s\n"
910 "%sProtectHome: %s\n"
911 "%sProtectSystem: %s\n"
912 "%sMountAPIVFS: %s\n"
913 "%sIgnoreSIGPIPE: %s\n"
914 "%sMemoryDenyWriteExecute: %s\n"
915 "%sRestrictRealtime: %s\n"
916 "%sRestrictSUIDSGID: %s\n"
917 "%sKeyringMode: %s\n"
918 "%sProtectHostname: %s\n"
919 "%sProtectProc: %s\n"
920 "%sProcSubset: %s\n",
922 prefix
, empty_to_root(c
->working_directory
),
923 prefix
, empty_to_root(c
->root_directory
),
924 prefix
, yes_no(c
->root_ephemeral
),
925 prefix
, yes_no(c
->non_blocking
),
926 prefix
, yes_no(c
->private_tmp
),
927 prefix
, yes_no(c
->private_devices
),
928 prefix
, yes_no(c
->protect_kernel_tunables
),
929 prefix
, yes_no(c
->protect_kernel_modules
),
930 prefix
, yes_no(c
->protect_kernel_logs
),
931 prefix
, yes_no(c
->protect_clock
),
932 prefix
, yes_no(c
->protect_control_groups
),
933 prefix
, yes_no(c
->private_network
),
934 prefix
, yes_no(c
->private_users
),
935 prefix
, protect_home_to_string(c
->protect_home
),
936 prefix
, protect_system_to_string(c
->protect_system
),
937 prefix
, yes_no(exec_context_get_effective_mount_apivfs(c
)),
938 prefix
, yes_no(c
->ignore_sigpipe
),
939 prefix
, yes_no(c
->memory_deny_write_execute
),
940 prefix
, yes_no(c
->restrict_realtime
),
941 prefix
, yes_no(c
->restrict_suid_sgid
),
942 prefix
, exec_keyring_mode_to_string(c
->keyring_mode
),
943 prefix
, yes_no(c
->protect_hostname
),
944 prefix
, protect_proc_to_string(c
->protect_proc
),
945 prefix
, proc_subset_to_string(c
->proc_subset
));
947 if (c
->set_login_environment
>= 0)
948 fprintf(f
, "%sSetLoginEnvironment: %s\n", prefix
, yes_no(c
->set_login_environment
> 0));
951 fprintf(f
, "%sRootImage: %s\n", prefix
, c
->root_image
);
953 if (c
->root_image_options
) {
954 fprintf(f
, "%sRootImageOptions:", prefix
);
955 LIST_FOREACH(mount_options
, o
, c
->root_image_options
)
956 if (!isempty(o
->options
))
958 partition_designator_to_string(o
->partition_designator
),
964 _cleanup_free_
char *encoded
= NULL
;
965 encoded
= hexmem(c
->root_hash
, c
->root_hash_size
);
967 fprintf(f
, "%sRootHash: %s\n", prefix
, encoded
);
970 if (c
->root_hash_path
)
971 fprintf(f
, "%sRootHash: %s\n", prefix
, c
->root_hash_path
);
973 if (c
->root_hash_sig
) {
974 _cleanup_free_
char *encoded
= NULL
;
976 len
= base64mem(c
->root_hash_sig
, c
->root_hash_sig_size
, &encoded
);
978 fprintf(f
, "%sRootHashSignature: base64:%s\n", prefix
, encoded
);
981 if (c
->root_hash_sig_path
)
982 fprintf(f
, "%sRootHashSignature: %s\n", prefix
, c
->root_hash_sig_path
);
985 fprintf(f
, "%sRootVerity: %s\n", prefix
, c
->root_verity
);
987 STRV_FOREACH(e
, c
->environment
)
988 fprintf(f
, "%sEnvironment: %s\n", prefix
, *e
);
990 STRV_FOREACH(e
, c
->environment_files
)
991 fprintf(f
, "%sEnvironmentFile: %s\n", prefix
, *e
);
993 STRV_FOREACH(e
, c
->pass_environment
)
994 fprintf(f
, "%sPassEnvironment: %s\n", prefix
, *e
);
996 STRV_FOREACH(e
, c
->unset_environment
)
997 fprintf(f
, "%sUnsetEnvironment: %s\n", prefix
, *e
);
999 fprintf(f
, "%sRuntimeDirectoryPreserve: %s\n", prefix
, exec_preserve_mode_to_string(c
->runtime_directory_preserve_mode
));
1001 for (ExecDirectoryType dt
= 0; dt
< _EXEC_DIRECTORY_TYPE_MAX
; dt
++) {
1002 fprintf(f
, "%s%sMode: %04o\n", prefix
, exec_directory_type_to_string(dt
), c
->directories
[dt
].mode
);
1004 for (size_t i
= 0; i
< c
->directories
[dt
].n_items
; i
++) {
1005 fprintf(f
, "%s%s: %s\n", prefix
, exec_directory_type_to_string(dt
), c
->directories
[dt
].items
[i
].path
);
1007 STRV_FOREACH(d
, c
->directories
[dt
].items
[i
].symlinks
)
1008 fprintf(f
, "%s%s: %s:%s\n", prefix
, exec_directory_type_symlink_to_string(dt
), c
->directories
[dt
].items
[i
].path
, *d
);
1012 fprintf(f
, "%sTimeoutCleanSec: %s\n", prefix
, FORMAT_TIMESPAN(c
->timeout_clean_usec
, USEC_PER_SEC
));
1014 if (c
->memory_ksm
>= 0)
1015 fprintf(f
, "%sMemoryKSM: %s\n", prefix
, yes_no(c
->memory_ksm
> 0));
1018 fprintf(f
, "%sNice: %i\n", prefix
, c
->nice
);
1020 if (c
->oom_score_adjust_set
)
1021 fprintf(f
, "%sOOMScoreAdjust: %i\n", prefix
, c
->oom_score_adjust
);
1023 if (c
->coredump_filter_set
)
1024 fprintf(f
, "%sCoredumpFilter: 0x%"PRIx64
"\n", prefix
, c
->coredump_filter
);
1026 for (unsigned i
= 0; i
< RLIM_NLIMITS
; i
++)
1028 fprintf(f
, "%sLimit%s: " RLIM_FMT
"\n",
1029 prefix
, rlimit_to_string(i
), c
->rlimit
[i
]->rlim_max
);
1030 fprintf(f
, "%sLimit%sSoft: " RLIM_FMT
"\n",
1031 prefix
, rlimit_to_string(i
), c
->rlimit
[i
]->rlim_cur
);
1034 if (c
->ioprio_set
) {
1035 _cleanup_free_
char *class_str
= NULL
;
1037 r
= ioprio_class_to_string_alloc(ioprio_prio_class(c
->ioprio
), &class_str
);
1039 fprintf(f
, "%sIOSchedulingClass: %s\n", prefix
, class_str
);
1041 fprintf(f
, "%sIOPriority: %d\n", prefix
, ioprio_prio_data(c
->ioprio
));
1044 if (c
->cpu_sched_set
) {
1045 _cleanup_free_
char *policy_str
= NULL
;
1047 r
= sched_policy_to_string_alloc(c
->cpu_sched_policy
, &policy_str
);
1049 fprintf(f
, "%sCPUSchedulingPolicy: %s\n", prefix
, policy_str
);
1052 "%sCPUSchedulingPriority: %i\n"
1053 "%sCPUSchedulingResetOnFork: %s\n",
1054 prefix
, c
->cpu_sched_priority
,
1055 prefix
, yes_no(c
->cpu_sched_reset_on_fork
));
1058 if (c
->cpu_set
.set
) {
1059 _cleanup_free_
char *affinity
= NULL
;
1061 affinity
= cpu_set_to_range_string(&c
->cpu_set
);
1062 fprintf(f
, "%sCPUAffinity: %s\n", prefix
, affinity
);
1065 if (mpol_is_valid(numa_policy_get_type(&c
->numa_policy
))) {
1066 _cleanup_free_
char *nodes
= NULL
;
1068 nodes
= cpu_set_to_range_string(&c
->numa_policy
.nodes
);
1069 fprintf(f
, "%sNUMAPolicy: %s\n", prefix
, mpol_to_string(numa_policy_get_type(&c
->numa_policy
)));
1070 fprintf(f
, "%sNUMAMask: %s\n", prefix
, strnull(nodes
));
1073 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
1074 fprintf(f
, "%sTimerSlackNSec: "NSEC_FMT
"\n", prefix
, c
->timer_slack_nsec
);
1077 "%sStandardInput: %s\n"
1078 "%sStandardOutput: %s\n"
1079 "%sStandardError: %s\n",
1080 prefix
, exec_input_to_string(c
->std_input
),
1081 prefix
, exec_output_to_string(c
->std_output
),
1082 prefix
, exec_output_to_string(c
->std_error
));
1084 if (c
->std_input
== EXEC_INPUT_NAMED_FD
)
1085 fprintf(f
, "%sStandardInputFileDescriptorName: %s\n", prefix
, c
->stdio_fdname
[STDIN_FILENO
]);
1086 if (c
->std_output
== EXEC_OUTPUT_NAMED_FD
)
1087 fprintf(f
, "%sStandardOutputFileDescriptorName: %s\n", prefix
, c
->stdio_fdname
[STDOUT_FILENO
]);
1088 if (c
->std_error
== EXEC_OUTPUT_NAMED_FD
)
1089 fprintf(f
, "%sStandardErrorFileDescriptorName: %s\n", prefix
, c
->stdio_fdname
[STDERR_FILENO
]);
1091 if (c
->std_input
== EXEC_INPUT_FILE
)
1092 fprintf(f
, "%sStandardInputFile: %s\n", prefix
, c
->stdio_file
[STDIN_FILENO
]);
1093 if (c
->std_output
== EXEC_OUTPUT_FILE
)
1094 fprintf(f
, "%sStandardOutputFile: %s\n", prefix
, c
->stdio_file
[STDOUT_FILENO
]);
1095 if (c
->std_output
== EXEC_OUTPUT_FILE_APPEND
)
1096 fprintf(f
, "%sStandardOutputFileToAppend: %s\n", prefix
, c
->stdio_file
[STDOUT_FILENO
]);
1097 if (c
->std_output
== EXEC_OUTPUT_FILE_TRUNCATE
)
1098 fprintf(f
, "%sStandardOutputFileToTruncate: %s\n", prefix
, c
->stdio_file
[STDOUT_FILENO
]);
1099 if (c
->std_error
== EXEC_OUTPUT_FILE
)
1100 fprintf(f
, "%sStandardErrorFile: %s\n", prefix
, c
->stdio_file
[STDERR_FILENO
]);
1101 if (c
->std_error
== EXEC_OUTPUT_FILE_APPEND
)
1102 fprintf(f
, "%sStandardErrorFileToAppend: %s\n", prefix
, c
->stdio_file
[STDERR_FILENO
]);
1103 if (c
->std_error
== EXEC_OUTPUT_FILE_TRUNCATE
)
1104 fprintf(f
, "%sStandardErrorFileToTruncate: %s\n", prefix
, c
->stdio_file
[STDERR_FILENO
]);
1110 "%sTTYVHangup: %s\n"
1111 "%sTTYVTDisallocate: %s\n"
1113 "%sTTYColumns: %u\n",
1114 prefix
, c
->tty_path
,
1115 prefix
, yes_no(c
->tty_reset
),
1116 prefix
, yes_no(c
->tty_vhangup
),
1117 prefix
, yes_no(c
->tty_vt_disallocate
),
1118 prefix
, c
->tty_rows
,
1119 prefix
, c
->tty_cols
);
1121 if (IN_SET(c
->std_output
,
1123 EXEC_OUTPUT_JOURNAL
,
1124 EXEC_OUTPUT_KMSG_AND_CONSOLE
,
1125 EXEC_OUTPUT_JOURNAL_AND_CONSOLE
) ||
1126 IN_SET(c
->std_error
,
1128 EXEC_OUTPUT_JOURNAL
,
1129 EXEC_OUTPUT_KMSG_AND_CONSOLE
,
1130 EXEC_OUTPUT_JOURNAL_AND_CONSOLE
)) {
1132 _cleanup_free_
char *fac_str
= NULL
, *lvl_str
= NULL
;
1134 r
= log_facility_unshifted_to_string_alloc(c
->syslog_priority
>> 3, &fac_str
);
1136 fprintf(f
, "%sSyslogFacility: %s\n", prefix
, fac_str
);
1138 r
= log_level_to_string_alloc(LOG_PRI(c
->syslog_priority
), &lvl_str
);
1140 fprintf(f
, "%sSyslogLevel: %s\n", prefix
, lvl_str
);
1143 if (c
->log_level_max
>= 0) {
1144 _cleanup_free_
char *t
= NULL
;
1146 (void) log_level_to_string_alloc(c
->log_level_max
, &t
);
1148 fprintf(f
, "%sLogLevelMax: %s\n", prefix
, strna(t
));
1151 if (c
->log_ratelimit_interval_usec
> 0)
1153 "%sLogRateLimitIntervalSec: %s\n",
1154 prefix
, FORMAT_TIMESPAN(c
->log_ratelimit_interval_usec
, USEC_PER_SEC
));
1156 if (c
->log_ratelimit_burst
> 0)
1157 fprintf(f
, "%sLogRateLimitBurst: %u\n", prefix
, c
->log_ratelimit_burst
);
1159 if (!set_isempty(c
->log_filter_allowed_patterns
) || !set_isempty(c
->log_filter_denied_patterns
)) {
1160 fprintf(f
, "%sLogFilterPatterns:", prefix
);
1163 SET_FOREACH(pattern
, c
->log_filter_allowed_patterns
)
1164 fprintf(f
, " %s", pattern
);
1165 SET_FOREACH(pattern
, c
->log_filter_denied_patterns
)
1166 fprintf(f
, " ~%s", pattern
);
1170 FOREACH_ARRAY(field
, c
->log_extra_fields
, c
->n_log_extra_fields
) {
1171 fprintf(f
, "%sLogExtraFields: ", prefix
);
1172 fwrite(field
->iov_base
, 1, field
->iov_len
, f
);
1176 if (c
->log_namespace
)
1177 fprintf(f
, "%sLogNamespace: %s\n", prefix
, c
->log_namespace
);
1179 if (c
->secure_bits
) {
1180 _cleanup_free_
char *str
= NULL
;
1182 r
= secure_bits_to_string_alloc(c
->secure_bits
, &str
);
1184 fprintf(f
, "%sSecure Bits: %s\n", prefix
, str
);
1187 if (c
->capability_bounding_set
!= CAP_MASK_UNSET
) {
1188 _cleanup_free_
char *str
= NULL
;
1190 r
= capability_set_to_string(c
->capability_bounding_set
, &str
);
1192 fprintf(f
, "%sCapabilityBoundingSet: %s\n", prefix
, str
);
1195 if (c
->capability_ambient_set
!= 0) {
1196 _cleanup_free_
char *str
= NULL
;
1198 r
= capability_set_to_string(c
->capability_ambient_set
, &str
);
1200 fprintf(f
, "%sAmbientCapabilities: %s\n", prefix
, str
);
1204 fprintf(f
, "%sUser: %s\n", prefix
, c
->user
);
1206 fprintf(f
, "%sGroup: %s\n", prefix
, c
->group
);
1208 fprintf(f
, "%sDynamicUser: %s\n", prefix
, yes_no(c
->dynamic_user
));
1210 strv_dump(f
, prefix
, "SupplementaryGroups", c
->supplementary_groups
);
1213 fprintf(f
, "%sPAMName: %s\n", prefix
, c
->pam_name
);
1215 strv_dump(f
, prefix
, "ReadWritePaths", c
->read_write_paths
);
1216 strv_dump(f
, prefix
, "ReadOnlyPaths", c
->read_only_paths
);
1217 strv_dump(f
, prefix
, "InaccessiblePaths", c
->inaccessible_paths
);
1218 strv_dump(f
, prefix
, "ExecPaths", c
->exec_paths
);
1219 strv_dump(f
, prefix
, "NoExecPaths", c
->no_exec_paths
);
1220 strv_dump(f
, prefix
, "ExecSearchPath", c
->exec_search_path
);
1222 FOREACH_ARRAY(mount
, c
->bind_mounts
, c
->n_bind_mounts
)
1223 fprintf(f
, "%s%s: %s%s:%s:%s\n", prefix
,
1224 mount
->read_only
? "BindReadOnlyPaths" : "BindPaths",
1225 mount
->ignore_enoent
? "-": "",
1228 mount
->recursive
? "rbind" : "norbind");
1230 FOREACH_ARRAY(tmpfs
, c
->temporary_filesystems
, c
->n_temporary_filesystems
)
1231 fprintf(f
, "%sTemporaryFileSystem: %s%s%s\n", prefix
,
1233 isempty(tmpfs
->options
) ? "" : ":",
1234 strempty(tmpfs
->options
));
1238 "%sUtmpIdentifier: %s\n",
1239 prefix
, c
->utmp_id
);
1241 if (c
->selinux_context
)
1243 "%sSELinuxContext: %s%s\n",
1244 prefix
, c
->selinux_context_ignore
? "-" : "", c
->selinux_context
);
1246 if (c
->apparmor_profile
)
1248 "%sAppArmorProfile: %s%s\n",
1249 prefix
, c
->apparmor_profile_ignore
? "-" : "", c
->apparmor_profile
);
1251 if (c
->smack_process_label
)
1253 "%sSmackProcessLabel: %s%s\n",
1254 prefix
, c
->smack_process_label_ignore
? "-" : "", c
->smack_process_label
);
1256 if (c
->personality
!= PERSONALITY_INVALID
)
1258 "%sPersonality: %s\n",
1259 prefix
, strna(personality_to_string(c
->personality
)));
1262 "%sLockPersonality: %s\n",
1263 prefix
, yes_no(c
->lock_personality
));
1265 if (c
->syscall_filter
) {
1267 "%sSystemCallFilter: ",
1270 if (!c
->syscall_allow_list
)
1276 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_filter
) {
1277 _cleanup_free_
char *name
= NULL
;
1278 const char *errno_name
= NULL
;
1279 int num
= PTR_TO_INT(val
);
1286 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
1287 fputs(strna(name
), f
);
1290 errno_name
= seccomp_errno_or_action_to_string(num
);
1292 fprintf(f
, ":%s", errno_name
);
1294 fprintf(f
, ":%d", num
);
1302 if (c
->syscall_archs
) {
1304 "%sSystemCallArchitectures:",
1309 SET_FOREACH(id
, c
->syscall_archs
)
1310 fprintf(f
, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1)));
1315 if (exec_context_restrict_namespaces_set(c
)) {
1316 _cleanup_free_
char *s
= NULL
;
1318 r
= namespace_flags_to_string(c
->restrict_namespaces
, &s
);
1320 fprintf(f
, "%sRestrictNamespaces: %s\n",
1325 if (exec_context_restrict_filesystems_set(c
)) {
1327 SET_FOREACH(fs
, c
->restrict_filesystems
)
1328 fprintf(f
, "%sRestrictFileSystems: %s\n", prefix
, fs
);
1332 if (c
->network_namespace_path
)
1334 "%sNetworkNamespacePath: %s\n",
1335 prefix
, c
->network_namespace_path
);
1337 if (c
->syscall_errno
> 0) {
1338 fprintf(f
, "%sSystemCallErrorNumber: ", prefix
);
1341 const char *errno_name
= seccomp_errno_or_action_to_string(c
->syscall_errno
);
1343 fputs(errno_name
, f
);
1345 fprintf(f
, "%d", c
->syscall_errno
);
1350 FOREACH_ARRAY(mount
, c
->mount_images
, c
->n_mount_images
) {
1351 fprintf(f
, "%sMountImages: %s%s:%s", prefix
,
1352 mount
->ignore_enoent
? "-": "",
1354 mount
->destination
);
1355 LIST_FOREACH(mount_options
, o
, mount
->mount_options
)
1356 fprintf(f
, ":%s:%s",
1357 partition_designator_to_string(o
->partition_designator
),
1358 strempty(o
->options
));
1362 FOREACH_ARRAY(mount
, c
->extension_images
, c
->n_extension_images
) {
1363 fprintf(f
, "%sExtensionImages: %s%s", prefix
,
1364 mount
->ignore_enoent
? "-": "",
1366 LIST_FOREACH(mount_options
, o
, mount
->mount_options
)
1367 fprintf(f
, ":%s:%s",
1368 partition_designator_to_string(o
->partition_designator
),
1369 strempty(o
->options
));
1373 strv_dump(f
, prefix
, "ExtensionDirectories", c
->extension_directories
);
1376 bool exec_context_maintains_privileges(const ExecContext
*c
) {
1379 /* Returns true if the process forked off would run under
1380 * an unchanged UID or as root. */
1385 if (streq(c
->user
, "root") || streq(c
->user
, "0"))
1391 int exec_context_get_effective_ioprio(const ExecContext
*c
) {
1399 p
= ioprio_get(IOPRIO_WHO_PROCESS
, 0);
1401 return IOPRIO_DEFAULT_CLASS_AND_PRIO
;
1403 return ioprio_normalize(p
);
1406 bool exec_context_get_effective_mount_apivfs(const ExecContext
*c
) {
1409 /* Explicit setting wins */
1410 if (c
->mount_apivfs_set
)
1411 return c
->mount_apivfs
;
1413 /* Default to "yes" if root directory or image are specified */
1414 if (exec_context_with_rootfs(c
))
1420 void exec_context_free_log_extra_fields(ExecContext
*c
) {
1423 FOREACH_ARRAY(field
, c
->log_extra_fields
, c
->n_log_extra_fields
)
1424 free(field
->iov_base
);
1426 c
->log_extra_fields
= mfree(c
->log_extra_fields
);
1427 c
->n_log_extra_fields
= 0;
1430 void exec_context_revert_tty(ExecContext
*c
) {
1431 _cleanup_close_
int fd
= -EBADF
;
1438 /* First, reset the TTY (possibly kicking everybody else from the TTY) */
1439 exec_context_tty_reset(c
, NULL
);
1441 /* And then undo what chown_terminal() did earlier. Note that we only do this if we have a path
1442 * configured. If the TTY was passed to us as file descriptor we assume the TTY is opened and managed
1443 * by whoever passed it to us and thus knows better when and how to chmod()/chown() it back. */
1444 if (!exec_context_may_touch_tty(c
))
1447 path
= exec_context_tty_path(c
);
1451 fd
= open(path
, O_PATH
|O_CLOEXEC
);
1453 return (void) log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_WARNING
, errno
,
1454 "Failed to open TTY inode of '%s' to adjust ownership/access mode, ignoring: %m",
1457 if (fstat(fd
, &st
) < 0)
1458 return (void) log_warning_errno(errno
, "Failed to stat TTY '%s', ignoring: %m", path
);
1460 /* Let's add a superficial check that we only do this for stuff that looks like a TTY. We only check
1461 * if things are a character device, since a proper check either means we'd have to open the TTY and
1462 * use isatty(), but we'd rather not do that since opening TTYs comes with all kinds of side-effects
1463 * and is slow. Or we'd have to hardcode dev_t major information, which we'd rather avoid. Why bother
1464 * with this at all? → https://github.com/systemd/systemd/issues/19213 */
1465 if (!S_ISCHR(st
.st_mode
))
1466 return log_warning("Configured TTY '%s' is not actually a character device, ignoring.", path
);
1468 r
= fchmod_and_chown(fd
, TTY_MODE
, 0, TTY_GID
);
1470 log_warning_errno(r
, "Failed to reset TTY ownership/access mode of %s, ignoring: %m", path
);
1473 int exec_context_get_clean_directories(
1479 _cleanup_strv_free_
char **l
= NULL
;
1486 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++) {
1487 if (!FLAGS_SET(mask
, 1U << t
))
1493 FOREACH_ARRAY(i
, c
->directories
[t
].items
, c
->directories
[t
].n_items
) {
1496 j
= path_join(prefix
[t
], i
->path
);
1500 r
= strv_consume(&l
, j
);
1504 /* Also remove private directories unconditionally. */
1505 if (t
!= EXEC_DIRECTORY_CONFIGURATION
) {
1506 j
= path_join(prefix
[t
], "private", i
->path
);
1510 r
= strv_consume(&l
, j
);
1515 STRV_FOREACH(symlink
, i
->symlinks
) {
1516 j
= path_join(prefix
[t
], *symlink
);
1520 r
= strv_consume(&l
, j
);
1531 int exec_context_get_clean_mask(ExecContext
*c
, ExecCleanMask
*ret
) {
1532 ExecCleanMask mask
= 0;
1537 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++)
1538 if (c
->directories
[t
].n_items
> 0)
1545 int exec_context_get_oom_score_adjust(const ExecContext
*c
) {
1550 if (c
->oom_score_adjust_set
)
1551 return c
->oom_score_adjust
;
1553 r
= get_oom_score_adjust(&n
);
1555 log_debug_errno(r
, "Failed to read /proc/self/oom_score_adj, ignoring: %m");
1560 uint64_t exec_context_get_coredump_filter(const ExecContext
*c
) {
1561 _cleanup_free_
char *t
= NULL
;
1562 uint64_t n
= COREDUMP_FILTER_MASK_DEFAULT
;
1567 if (c
->coredump_filter_set
)
1568 return c
->coredump_filter
;
1570 r
= read_one_line_file("/proc/self/coredump_filter", &t
);
1572 log_debug_errno(r
, "Failed to read /proc/self/coredump_filter, ignoring: %m");
1574 r
= safe_atoux64(t
, &n
);
1576 log_debug_errno(r
, "Failed to parse \"%s\" from /proc/self/coredump_filter, ignoring: %m", t
);
1582 int exec_context_get_nice(const ExecContext
*c
) {
1591 n
= getpriority(PRIO_PROCESS
, 0);
1593 log_debug_errno(errno
, "Failed to get process nice value, ignoring: %m");
1600 int exec_context_get_cpu_sched_policy(const ExecContext
*c
) {
1605 if (c
->cpu_sched_set
)
1606 return c
->cpu_sched_policy
;
1608 n
= sched_getscheduler(0);
1610 log_debug_errno(errno
, "Failed to get scheduler policy, ignoring: %m");
1612 return n
< 0 ? SCHED_OTHER
: n
;
1615 int exec_context_get_cpu_sched_priority(const ExecContext
*c
) {
1616 struct sched_param p
= {};
1621 if (c
->cpu_sched_set
)
1622 return c
->cpu_sched_priority
;
1624 r
= sched_getparam(0, &p
);
1626 log_debug_errno(errno
, "Failed to get scheduler priority, ignoring: %m");
1628 return r
>= 0 ? p
.sched_priority
: 0;
1631 uint64_t exec_context_get_timer_slack_nsec(const ExecContext
*c
) {
1636 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
1637 return c
->timer_slack_nsec
;
1639 r
= prctl(PR_GET_TIMERSLACK
);
1641 log_debug_errno(r
, "Failed to get timer slack, ignoring: %m");
1643 return (uint64_t) MAX(r
, 0);
1646 char** exec_context_get_syscall_filter(const ExecContext
*c
) {
1647 _cleanup_strv_free_
char **l
= NULL
;
1653 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_filter
) {
1654 _cleanup_free_
char *name
= NULL
;
1655 const char *e
= NULL
;
1657 int num
= PTR_TO_INT(val
);
1659 if (c
->syscall_allow_list
&& num
>= 0)
1660 /* syscall with num >= 0 in allow-list is denied. */
1663 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
1668 e
= seccomp_errno_or_action_to_string(num
);
1670 s
= strjoin(name
, ":", e
);
1674 if (asprintf(&s
, "%s:%d", name
, num
) < 0)
1680 if (strv_consume(&l
, s
) < 0)
1687 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1690 char** exec_context_get_syscall_archs(const ExecContext
*c
) {
1691 _cleanup_strv_free_
char **l
= NULL
;
1697 SET_FOREACH(id
, c
->syscall_archs
) {
1700 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
1704 if (strv_extend(&l
, name
) < 0)
1711 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1714 char** exec_context_get_syscall_log(const ExecContext
*c
) {
1715 _cleanup_strv_free_
char **l
= NULL
;
1721 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_log
) {
1724 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
1728 if (strv_consume(&l
, name
) < 0)
1735 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1738 char** exec_context_get_address_families(const ExecContext
*c
) {
1739 _cleanup_strv_free_
char **l
= NULL
;
1744 SET_FOREACH(af
, c
->address_families
) {
1747 name
= af_to_name(PTR_TO_INT(af
));
1751 if (strv_extend(&l
, name
) < 0)
1757 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1760 char** exec_context_get_restrict_filesystems(const ExecContext
*c
) {
1761 _cleanup_strv_free_
char **l
= NULL
;
1766 l
= set_get_strv(c
->restrict_filesystems
);
1773 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1776 void exec_status_start(ExecStatus
*s
, pid_t pid
) {
1783 dual_timestamp_get(&s
->start_timestamp
);
1786 void exec_status_exit(ExecStatus
*s
, const ExecContext
*context
, pid_t pid
, int code
, int status
) {
1794 dual_timestamp_get(&s
->exit_timestamp
);
1799 if (context
&& context
->utmp_id
)
1800 (void) utmp_put_dead_process(context
->utmp_id
, pid
, code
, status
);
1803 void exec_status_reset(ExecStatus
*s
) {
1806 *s
= (ExecStatus
) {};
1809 void exec_status_dump(const ExecStatus
*s
, FILE *f
, const char *prefix
) {
1816 prefix
= strempty(prefix
);
1819 "%sPID: "PID_FMT
"\n",
1822 if (dual_timestamp_is_set(&s
->start_timestamp
))
1824 "%sStart Timestamp: %s\n",
1825 prefix
, FORMAT_TIMESTAMP(s
->start_timestamp
.realtime
));
1827 if (dual_timestamp_is_set(&s
->exit_timestamp
))
1829 "%sExit Timestamp: %s\n"
1831 "%sExit Status: %i\n",
1832 prefix
, FORMAT_TIMESTAMP(s
->exit_timestamp
.realtime
),
1833 prefix
, sigchld_code_to_string(s
->code
),
1837 static void exec_command_dump(ExecCommand
*c
, FILE *f
, const char *prefix
) {
1838 _cleanup_free_
char *cmd
= NULL
;
1839 const char *prefix2
;
1844 prefix
= strempty(prefix
);
1845 prefix2
= strjoina(prefix
, "\t");
1847 cmd
= quote_command_line(c
->argv
, SHELL_ESCAPE_EMPTY
);
1850 "%sCommand Line: %s\n",
1851 prefix
, strnull(cmd
));
1853 exec_status_dump(&c
->exec_status
, f
, prefix2
);
1856 void exec_command_dump_list(ExecCommand
*c
, FILE *f
, const char *prefix
) {
1859 prefix
= strempty(prefix
);
1861 LIST_FOREACH(command
, i
, c
)
1862 exec_command_dump(i
, f
, prefix
);
1865 void exec_command_append_list(ExecCommand
**l
, ExecCommand
*e
) {
1872 /* It's kind of important, that we keep the order here */
1873 end
= LIST_FIND_TAIL(command
, *l
);
1874 LIST_INSERT_AFTER(command
, *l
, end
, e
);
1879 int exec_command_set(ExecCommand
*c
, const char *path
, ...) {
1887 l
= strv_new_ap(path
, ap
);
1899 free_and_replace(c
->path
, p
);
1901 return strv_free_and_replace(c
->argv
, l
);
1904 int exec_command_append(ExecCommand
*c
, const char *path
, ...) {
1905 _cleanup_strv_free_
char **l
= NULL
;
1913 l
= strv_new_ap(path
, ap
);
1919 r
= strv_extend_strv(&c
->argv
, l
, false);
1926 static char *destroy_tree(char *path
) {
1930 if (!path_equal(path
, RUN_SYSTEMD_EMPTY
)) {
1931 log_debug("Spawning process to nuke '%s'", path
);
1933 (void) asynchronous_rm_rf(path
, REMOVE_ROOT
|REMOVE_SUBVOLUME
|REMOVE_PHYSICAL
);
1939 void exec_shared_runtime_done(ExecSharedRuntime
*rt
) {
1944 (void) hashmap_remove(rt
->manager
->exec_shared_runtime_by_id
, rt
->id
);
1946 rt
->id
= mfree(rt
->id
);
1947 rt
->tmp_dir
= mfree(rt
->tmp_dir
);
1948 rt
->var_tmp_dir
= mfree(rt
->var_tmp_dir
);
1949 safe_close_pair(rt
->netns_storage_socket
);
1950 safe_close_pair(rt
->ipcns_storage_socket
);
1953 static ExecSharedRuntime
* exec_shared_runtime_free(ExecSharedRuntime
*rt
) {
1954 exec_shared_runtime_done(rt
);
1959 DEFINE_TRIVIAL_UNREF_FUNC(ExecSharedRuntime
, exec_shared_runtime
, exec_shared_runtime_free
);
1960 DEFINE_TRIVIAL_CLEANUP_FUNC(ExecSharedRuntime
*, exec_shared_runtime_free
);
1962 ExecSharedRuntime
* exec_shared_runtime_destroy(ExecSharedRuntime
*rt
) {
1966 assert(rt
->n_ref
> 0);
1972 rt
->tmp_dir
= destroy_tree(rt
->tmp_dir
);
1973 rt
->var_tmp_dir
= destroy_tree(rt
->var_tmp_dir
);
1975 return exec_shared_runtime_free(rt
);
1978 static int exec_shared_runtime_allocate(ExecSharedRuntime
**ret
, const char *id
) {
1979 _cleanup_free_
char *id_copy
= NULL
;
1980 ExecSharedRuntime
*n
;
1984 id_copy
= strdup(id
);
1988 n
= new(ExecSharedRuntime
, 1);
1992 *n
= (ExecSharedRuntime
) {
1993 .id
= TAKE_PTR(id_copy
),
1994 .netns_storage_socket
= PIPE_EBADF
,
1995 .ipcns_storage_socket
= PIPE_EBADF
,
2002 static int exec_shared_runtime_add(
2007 int netns_storage_socket
[2],
2008 int ipcns_storage_socket
[2],
2009 ExecSharedRuntime
**ret
) {
2011 _cleanup_(exec_shared_runtime_freep
) ExecSharedRuntime
*rt
= NULL
;
2017 /* tmp_dir, var_tmp_dir, {net,ipc}ns_storage_socket fds are donated on success */
2019 r
= exec_shared_runtime_allocate(&rt
, id
);
2023 r
= hashmap_ensure_put(&m
->exec_shared_runtime_by_id
, &string_hash_ops
, rt
->id
, rt
);
2027 assert(!!rt
->tmp_dir
== !!rt
->var_tmp_dir
); /* We require both to be set together */
2028 rt
->tmp_dir
= TAKE_PTR(*tmp_dir
);
2029 rt
->var_tmp_dir
= TAKE_PTR(*var_tmp_dir
);
2031 if (netns_storage_socket
) {
2032 rt
->netns_storage_socket
[0] = TAKE_FD(netns_storage_socket
[0]);
2033 rt
->netns_storage_socket
[1] = TAKE_FD(netns_storage_socket
[1]);
2036 if (ipcns_storage_socket
) {
2037 rt
->ipcns_storage_socket
[0] = TAKE_FD(ipcns_storage_socket
[0]);
2038 rt
->ipcns_storage_socket
[1] = TAKE_FD(ipcns_storage_socket
[1]);
2045 /* do not remove created ExecSharedRuntime object when the operation succeeds. */
2050 static int exec_shared_runtime_make(
2052 const ExecContext
*c
,
2054 ExecSharedRuntime
**ret
) {
2056 _cleanup_(namespace_cleanup_tmpdirp
) char *tmp_dir
= NULL
, *var_tmp_dir
= NULL
;
2057 _cleanup_close_pair_
int netns_storage_socket
[2] = PIPE_EBADF
, ipcns_storage_socket
[2] = PIPE_EBADF
;
2064 /* It is not necessary to create ExecSharedRuntime object. */
2065 if (!exec_needs_network_namespace(c
) && !exec_needs_ipc_namespace(c
) && !c
->private_tmp
) {
2070 if (c
->private_tmp
&&
2071 !(prefixed_path_strv_contains(c
->inaccessible_paths
, "/tmp") &&
2072 (prefixed_path_strv_contains(c
->inaccessible_paths
, "/var/tmp") ||
2073 prefixed_path_strv_contains(c
->inaccessible_paths
, "/var")))) {
2074 r
= setup_tmp_dirs(id
, &tmp_dir
, &var_tmp_dir
);
2079 if (exec_needs_network_namespace(c
)) {
2080 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, netns_storage_socket
) < 0)
2084 if (exec_needs_ipc_namespace(c
)) {
2085 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, ipcns_storage_socket
) < 0)
2089 r
= exec_shared_runtime_add(m
, id
, &tmp_dir
, &var_tmp_dir
, netns_storage_socket
, ipcns_storage_socket
, ret
);
2096 int exec_shared_runtime_acquire(Manager
*m
, const ExecContext
*c
, const char *id
, bool create
, ExecSharedRuntime
**ret
) {
2097 ExecSharedRuntime
*rt
;
2104 rt
= hashmap_get(m
->exec_shared_runtime_by_id
, id
);
2106 /* We already have an ExecSharedRuntime object, let's increase the ref count and reuse it */
2114 /* If not found, then create a new object. */
2115 r
= exec_shared_runtime_make(m
, c
, id
, &rt
);
2119 /* When r == 0, it is not necessary to create ExecSharedRuntime object. */
2125 /* increment reference counter. */
2131 int exec_shared_runtime_serialize(const Manager
*m
, FILE *f
, FDSet
*fds
) {
2132 ExecSharedRuntime
*rt
;
2138 HASHMAP_FOREACH(rt
, m
->exec_shared_runtime_by_id
) {
2139 fprintf(f
, "exec-runtime=%s", rt
->id
);
2142 fprintf(f
, " tmp-dir=%s", rt
->tmp_dir
);
2144 if (rt
->var_tmp_dir
)
2145 fprintf(f
, " var-tmp-dir=%s", rt
->var_tmp_dir
);
2147 if (rt
->netns_storage_socket
[0] >= 0) {
2150 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[0]);
2154 fprintf(f
, " netns-socket-0=%i", copy
);
2157 if (rt
->netns_storage_socket
[1] >= 0) {
2160 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[1]);
2164 fprintf(f
, " netns-socket-1=%i", copy
);
2167 if (rt
->ipcns_storage_socket
[0] >= 0) {
2170 copy
= fdset_put_dup(fds
, rt
->ipcns_storage_socket
[0]);
2174 fprintf(f
, " ipcns-socket-0=%i", copy
);
2177 if (rt
->ipcns_storage_socket
[1] >= 0) {
2180 copy
= fdset_put_dup(fds
, rt
->ipcns_storage_socket
[1]);
2184 fprintf(f
, " ipcns-socket-1=%i", copy
);
2193 int exec_shared_runtime_deserialize_compat(Unit
*u
, const char *key
, const char *value
, FDSet
*fds
) {
2194 _cleanup_(exec_shared_runtime_freep
) ExecSharedRuntime
*rt_create
= NULL
;
2195 ExecSharedRuntime
*rt
= NULL
;
2198 /* This is for the migration from old (v237 or earlier) deserialization text.
2199 * Due to the bug #7790, this may not work with the units that use JoinsNamespaceOf=.
2200 * Even if the ExecSharedRuntime object originally created by the other unit, we cannot judge
2201 * so or not from the serialized text, then we always creates a new object owned by this. */
2207 /* Manager manages ExecSharedRuntime objects by the unit id.
2208 * So, we omit the serialized text when the unit does not have id (yet?)... */
2209 if (isempty(u
->id
)) {
2210 log_unit_debug(u
, "Invocation ID not found. Dropping runtime parameter.");
2215 if (hashmap_ensure_allocated(&u
->manager
->exec_shared_runtime_by_id
, &string_hash_ops
) < 0)
2218 rt
= hashmap_get(u
->manager
->exec_shared_runtime_by_id
, u
->id
);
2221 if (exec_shared_runtime_allocate(&rt_create
, u
->id
) < 0)
2227 if (streq(key
, "tmp-dir")) {
2228 if (free_and_strdup_warn(&rt
->tmp_dir
, value
) < 0)
2231 } else if (streq(key
, "var-tmp-dir")) {
2232 if (free_and_strdup_warn(&rt
->var_tmp_dir
, value
) < 0)
2235 } else if (streq(key
, "netns-socket-0")) {
2237 safe_close(rt
->netns_storage_socket
[0]);
2238 rt
->netns_storage_socket
[0] = deserialize_fd(fds
, value
);
2239 if (rt
->netns_storage_socket
[0] < 0)
2242 } else if (streq(key
, "netns-socket-1")) {
2244 safe_close(rt
->netns_storage_socket
[1]);
2245 rt
->netns_storage_socket
[1] = deserialize_fd(fds
, value
);
2246 if (rt
->netns_storage_socket
[1] < 0)
2251 /* If the object is newly created, then put it to the hashmap which manages ExecSharedRuntime objects. */
2252 if (rt_create
&& u
->manager
) {
2253 r
= hashmap_put(u
->manager
->exec_shared_runtime_by_id
, rt_create
->id
, rt_create
);
2255 log_unit_debug_errno(u
, r
, "Failed to put runtime parameter to manager's storage: %m");
2259 rt_create
->manager
= u
->manager
;
2262 TAKE_PTR(rt_create
);
2268 int exec_shared_runtime_deserialize_one(Manager
*m
, const char *value
, FDSet
*fds
) {
2269 _cleanup_free_
char *tmp_dir
= NULL
, *var_tmp_dir
= NULL
;
2271 int r
, netns_fdpair
[] = {-1, -1}, ipcns_fdpair
[] = {-1, -1};
2272 const char *p
, *v
= ASSERT_PTR(value
);
2278 n
= strcspn(v
, " ");
2279 id
= strndupa_safe(v
, n
);
2284 v
= startswith(p
, "tmp-dir=");
2286 n
= strcspn(v
, " ");
2287 tmp_dir
= strndup(v
, n
);
2295 v
= startswith(p
, "var-tmp-dir=");
2297 n
= strcspn(v
, " ");
2298 var_tmp_dir
= strndup(v
, n
);
2306 v
= startswith(p
, "netns-socket-0=");
2310 n
= strcspn(v
, " ");
2311 buf
= strndupa_safe(v
, n
);
2313 netns_fdpair
[0] = deserialize_fd(fds
, buf
);
2314 if (netns_fdpair
[0] < 0)
2315 return netns_fdpair
[0];
2321 v
= startswith(p
, "netns-socket-1=");
2325 n
= strcspn(v
, " ");
2326 buf
= strndupa_safe(v
, n
);
2328 netns_fdpair
[1] = deserialize_fd(fds
, buf
);
2329 if (netns_fdpair
[1] < 0)
2330 return netns_fdpair
[1];
2336 v
= startswith(p
, "ipcns-socket-0=");
2340 n
= strcspn(v
, " ");
2341 buf
= strndupa_safe(v
, n
);
2343 ipcns_fdpair
[0] = deserialize_fd(fds
, buf
);
2344 if (ipcns_fdpair
[0] < 0)
2345 return ipcns_fdpair
[0];
2351 v
= startswith(p
, "ipcns-socket-1=");
2355 n
= strcspn(v
, " ");
2356 buf
= strndupa_safe(v
, n
);
2358 ipcns_fdpair
[1] = deserialize_fd(fds
, buf
);
2359 if (ipcns_fdpair
[1] < 0)
2360 return ipcns_fdpair
[1];
2364 r
= exec_shared_runtime_add(m
, id
, &tmp_dir
, &var_tmp_dir
, netns_fdpair
, ipcns_fdpair
, NULL
);
2366 return log_debug_errno(r
, "Failed to add exec-runtime: %m");
2370 void exec_shared_runtime_vacuum(Manager
*m
) {
2371 ExecSharedRuntime
*rt
;
2375 /* Free unreferenced ExecSharedRuntime objects. This is used after manager deserialization process. */
2377 HASHMAP_FOREACH(rt
, m
->exec_shared_runtime_by_id
) {
2381 (void) exec_shared_runtime_free(rt
);
2385 int exec_runtime_make(
2387 const ExecContext
*context
,
2388 ExecSharedRuntime
*shared
,
2389 DynamicCreds
*creds
,
2390 ExecRuntime
**ret
) {
2391 _cleanup_close_pair_
int ephemeral_storage_socket
[2] = PIPE_EBADF
;
2392 _cleanup_free_
char *ephemeral
= NULL
;
2393 _cleanup_(exec_runtime_freep
) ExecRuntime
*rt
= NULL
;
2400 if (!shared
&& !creds
&& !exec_needs_ephemeral(context
)) {
2405 if (exec_needs_ephemeral(context
)) {
2406 r
= mkdir_p("/var/lib/systemd/ephemeral-trees", 0755);
2410 r
= tempfn_random_child("/var/lib/systemd/ephemeral-trees", unit
->id
, &ephemeral
);
2414 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, ephemeral_storage_socket
) < 0)
2418 rt
= new(ExecRuntime
, 1);
2422 *rt
= (ExecRuntime
) {
2424 .dynamic_creds
= creds
,
2425 .ephemeral_copy
= TAKE_PTR(ephemeral
),
2426 .ephemeral_storage_socket
[0] = TAKE_FD(ephemeral_storage_socket
[0]),
2427 .ephemeral_storage_socket
[1] = TAKE_FD(ephemeral_storage_socket
[1]),
2430 *ret
= TAKE_PTR(rt
);
2434 ExecRuntime
* exec_runtime_free(ExecRuntime
*rt
) {
2438 exec_shared_runtime_unref(rt
->shared
);
2439 dynamic_creds_unref(rt
->dynamic_creds
);
2441 rt
->ephemeral_copy
= destroy_tree(rt
->ephemeral_copy
);
2443 safe_close_pair(rt
->ephemeral_storage_socket
);
2447 ExecRuntime
* exec_runtime_destroy(ExecRuntime
*rt
) {
2451 rt
->shared
= exec_shared_runtime_destroy(rt
->shared
);
2452 rt
->dynamic_creds
= dynamic_creds_destroy(rt
->dynamic_creds
);
2453 return exec_runtime_free(rt
);
2456 void exec_runtime_clear(ExecRuntime
*rt
) {
2460 safe_close_pair(rt
->ephemeral_storage_socket
);
2461 rt
->ephemeral_copy
= mfree(rt
->ephemeral_copy
);
2464 void exec_params_clear(ExecParameters
*p
) {
2468 p
->environment
= strv_free(p
->environment
);
2469 p
->fd_names
= strv_free(p
->fd_names
);
2470 p
->files_env
= strv_free(p
->files_env
);
2471 p
->fds
= mfree(p
->fds
);
2472 p
->exec_fd
= safe_close(p
->exec_fd
);
2473 p
->user_lookup_fd
= -EBADF
;
2474 p
->bpf_outer_map_fd
= -EBADF
;
2475 p
->unit_id
= mfree(p
->unit_id
);
2476 p
->invocation_id
= SD_ID128_NULL
;
2477 p
->invocation_id_string
[0] = '\0';
2478 p
->confirm_spawn
= mfree(p
->confirm_spawn
);
2481 void exec_params_serialized_done(ExecParameters
*p
) {
2485 close_many_unset(p
->fds
, p
->n_socket_fds
+ p
->n_storage_fds
);
2487 p
->cgroup_path
= mfree(p
->cgroup_path
);
2490 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++)
2493 p
->prefix
= mfree(p
->prefix
);
2496 p
->received_credentials_directory
= mfree(p
->received_credentials_directory
);
2497 p
->received_encrypted_credentials_directory
= mfree(p
->received_encrypted_credentials_directory
);
2500 close_many_and_free(p
->idle_pipe
, 4);
2501 p
->idle_pipe
= NULL
;
2504 p
->stdin_fd
= safe_close(p
->stdin_fd
);
2505 p
->stdout_fd
= safe_close(p
->stdout_fd
);
2506 p
->stderr_fd
= safe_close(p
->stderr_fd
);
2508 p
->notify_socket
= mfree(p
->notify_socket
);
2510 open_file_free_many(&p
->open_files
);
2512 p
->fallback_smack_process_label
= mfree(p
->fallback_smack_process_label
);
2514 exec_params_clear(p
);
2517 void exec_directory_done(ExecDirectory
*d
) {
2521 FOREACH_ARRAY(i
, d
->items
, d
->n_items
) {
2523 strv_free(i
->symlinks
);
2526 d
->items
= mfree(d
->items
);
2531 static ExecDirectoryItem
*exec_directory_find(ExecDirectory
*d
, const char *path
) {
2535 FOREACH_ARRAY(i
, d
->items
, d
->n_items
)
2536 if (path_equal(i
->path
, path
))
2542 int exec_directory_add(ExecDirectory
*d
, const char *path
, const char *symlink
) {
2543 _cleanup_strv_free_
char **s
= NULL
;
2544 _cleanup_free_
char *p
= NULL
;
2545 ExecDirectoryItem
*existing
;
2551 existing
= exec_directory_find(d
, path
);
2553 r
= strv_extend(&existing
->symlinks
, symlink
);
2557 return 0; /* existing item is updated */
2565 s
= strv_new(symlink
);
2570 if (!GREEDY_REALLOC(d
->items
, d
->n_items
+ 1))
2573 d
->items
[d
->n_items
++] = (ExecDirectoryItem
) {
2574 .path
= TAKE_PTR(p
),
2575 .symlinks
= TAKE_PTR(s
),
2578 return 1; /* new item is added */
2581 static int exec_directory_item_compare_func(const ExecDirectoryItem
*a
, const ExecDirectoryItem
*b
) {
2585 return path_compare(a
->path
, b
->path
);
2588 void exec_directory_sort(ExecDirectory
*d
) {
2591 /* Sort the exec directories to make always parent directories processed at first in
2592 * setup_exec_directory(), e.g., even if StateDirectory=foo/bar foo, we need to create foo at first,
2593 * then foo/bar. Also, set .only_create flag if one of the parent directories is contained in the
2594 * list. See also comments in setup_exec_directory() and issue #24783. */
2596 if (d
->n_items
<= 1)
2599 typesafe_qsort(d
->items
, d
->n_items
, exec_directory_item_compare_func
);
2601 for (size_t i
= 1; i
< d
->n_items
; i
++)
2602 for (size_t j
= 0; j
< i
; j
++)
2603 if (path_startswith(d
->items
[i
].path
, d
->items
[j
].path
)) {
2604 d
->items
[i
].only_create
= true;
2609 ExecCleanMask
exec_clean_mask_from_string(const char *s
) {
2610 ExecDirectoryType t
;
2614 if (streq(s
, "all"))
2615 return EXEC_CLEAN_ALL
;
2616 if (streq(s
, "fdstore"))
2617 return EXEC_CLEAN_FDSTORE
;
2619 t
= exec_resource_type_from_string(s
);
2621 return (ExecCleanMask
) t
;
2626 static const char* const exec_input_table
[_EXEC_INPUT_MAX
] = {
2627 [EXEC_INPUT_NULL
] = "null",
2628 [EXEC_INPUT_TTY
] = "tty",
2629 [EXEC_INPUT_TTY_FORCE
] = "tty-force",
2630 [EXEC_INPUT_TTY_FAIL
] = "tty-fail",
2631 [EXEC_INPUT_SOCKET
] = "socket",
2632 [EXEC_INPUT_NAMED_FD
] = "fd",
2633 [EXEC_INPUT_DATA
] = "data",
2634 [EXEC_INPUT_FILE
] = "file",
2637 DEFINE_STRING_TABLE_LOOKUP(exec_input
, ExecInput
);
2639 static const char* const exec_output_table
[_EXEC_OUTPUT_MAX
] = {
2640 [EXEC_OUTPUT_INHERIT
] = "inherit",
2641 [EXEC_OUTPUT_NULL
] = "null",
2642 [EXEC_OUTPUT_TTY
] = "tty",
2643 [EXEC_OUTPUT_KMSG
] = "kmsg",
2644 [EXEC_OUTPUT_KMSG_AND_CONSOLE
] = "kmsg+console",
2645 [EXEC_OUTPUT_JOURNAL
] = "journal",
2646 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE
] = "journal+console",
2647 [EXEC_OUTPUT_SOCKET
] = "socket",
2648 [EXEC_OUTPUT_NAMED_FD
] = "fd",
2649 [EXEC_OUTPUT_FILE
] = "file",
2650 [EXEC_OUTPUT_FILE_APPEND
] = "append",
2651 [EXEC_OUTPUT_FILE_TRUNCATE
] = "truncate",
2654 DEFINE_STRING_TABLE_LOOKUP(exec_output
, ExecOutput
);
2656 static const char* const exec_utmp_mode_table
[_EXEC_UTMP_MODE_MAX
] = {
2657 [EXEC_UTMP_INIT
] = "init",
2658 [EXEC_UTMP_LOGIN
] = "login",
2659 [EXEC_UTMP_USER
] = "user",
2662 DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode
, ExecUtmpMode
);
2664 static const char* const exec_preserve_mode_table
[_EXEC_PRESERVE_MODE_MAX
] = {
2665 [EXEC_PRESERVE_NO
] = "no",
2666 [EXEC_PRESERVE_YES
] = "yes",
2667 [EXEC_PRESERVE_RESTART
] = "restart",
2670 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode
, ExecPreserveMode
, EXEC_PRESERVE_YES
);
2672 /* This table maps ExecDirectoryType to the setting it is configured with in the unit */
2673 static const char* const exec_directory_type_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2674 [EXEC_DIRECTORY_RUNTIME
] = "RuntimeDirectory",
2675 [EXEC_DIRECTORY_STATE
] = "StateDirectory",
2676 [EXEC_DIRECTORY_CACHE
] = "CacheDirectory",
2677 [EXEC_DIRECTORY_LOGS
] = "LogsDirectory",
2678 [EXEC_DIRECTORY_CONFIGURATION
] = "ConfigurationDirectory",
2681 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type
, ExecDirectoryType
);
2683 /* This table maps ExecDirectoryType to the symlink setting it is configured with in the unit */
2684 static const char* const exec_directory_type_symlink_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2685 [EXEC_DIRECTORY_RUNTIME
] = "RuntimeDirectorySymlink",
2686 [EXEC_DIRECTORY_STATE
] = "StateDirectorySymlink",
2687 [EXEC_DIRECTORY_CACHE
] = "CacheDirectorySymlink",
2688 [EXEC_DIRECTORY_LOGS
] = "LogsDirectorySymlink",
2689 [EXEC_DIRECTORY_CONFIGURATION
] = "ConfigurationDirectorySymlink",
2692 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type_symlink
, ExecDirectoryType
);
2694 static const char* const exec_directory_type_mode_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2695 [EXEC_DIRECTORY_RUNTIME
] = "RuntimeDirectoryMode",
2696 [EXEC_DIRECTORY_STATE
] = "StateDirectoryMode",
2697 [EXEC_DIRECTORY_CACHE
] = "CacheDirectoryMode",
2698 [EXEC_DIRECTORY_LOGS
] = "LogsDirectoryMode",
2699 [EXEC_DIRECTORY_CONFIGURATION
] = "ConfigurationDirectoryMode",
2702 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type_mode
, ExecDirectoryType
);
2704 /* And this table maps ExecDirectoryType too, but to a generic term identifying the type of resource. This
2705 * one is supposed to be generic enough to be used for unit types that don't use ExecContext and per-unit
2706 * directories, specifically .timer units with their timestamp touch file. */
2707 static const char* const exec_resource_type_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2708 [EXEC_DIRECTORY_RUNTIME
] = "runtime",
2709 [EXEC_DIRECTORY_STATE
] = "state",
2710 [EXEC_DIRECTORY_CACHE
] = "cache",
2711 [EXEC_DIRECTORY_LOGS
] = "logs",
2712 [EXEC_DIRECTORY_CONFIGURATION
] = "configuration",
2715 DEFINE_STRING_TABLE_LOOKUP(exec_resource_type
, ExecDirectoryType
);
2717 static const char* const exec_keyring_mode_table
[_EXEC_KEYRING_MODE_MAX
] = {
2718 [EXEC_KEYRING_INHERIT
] = "inherit",
2719 [EXEC_KEYRING_PRIVATE
] = "private",
2720 [EXEC_KEYRING_SHARED
] = "shared",
2723 DEFINE_STRING_TABLE_LOOKUP(exec_keyring_mode
, ExecKeyringMode
);