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_safe(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();
164 if (ERRNO_IS_NEG_PRIVILEGE(lock_fd
))
165 log_debug_errno(lock_fd
, "No privileges to lock /dev/console, proceeding without: %m");
166 else if (ERRNO_IS_NEG_DEVICE_ABSENT(lock_fd
))
167 log_debug_errno(lock_fd
, "Device /dev/console does not exist, proceeding without locking it: %m");
168 else if (lock_fd
< 0)
169 return (void) log_debug_errno(lock_fd
, "Failed to lock /dev/console: %m");
171 if (context
->tty_vhangup
)
172 (void) terminal_vhangup_fd(fd
);
174 if (context
->tty_reset
)
175 (void) reset_terminal_fd(fd
, /* switch_to_text= */ true);
177 (void) exec_context_apply_tty_size(context
, fd
, path
);
179 if (context
->tty_vt_disallocate
&& path
)
180 (void) vt_disallocate(path
);
183 bool exec_needs_network_namespace(const ExecContext
*context
) {
186 return context
->private_network
|| context
->network_namespace_path
;
189 static bool exec_needs_ephemeral(const ExecContext
*context
) {
190 return (context
->root_image
|| context
->root_directory
) && context
->root_ephemeral
;
193 bool exec_needs_ipc_namespace(const ExecContext
*context
) {
196 return context
->private_ipc
|| context
->ipc_namespace_path
;
199 bool exec_needs_mount_namespace(
200 const ExecContext
*context
,
201 const ExecParameters
*params
,
202 const ExecRuntime
*runtime
) {
206 if (context
->root_image
)
209 if (!strv_isempty(context
->read_write_paths
) ||
210 !strv_isempty(context
->read_only_paths
) ||
211 !strv_isempty(context
->inaccessible_paths
) ||
212 !strv_isempty(context
->exec_paths
) ||
213 !strv_isempty(context
->no_exec_paths
))
216 if (context
->n_bind_mounts
> 0)
219 if (context
->n_temporary_filesystems
> 0)
222 if (context
->n_mount_images
> 0)
225 if (context
->n_extension_images
> 0)
228 if (!strv_isempty(context
->extension_directories
))
231 if (!IN_SET(context
->mount_propagation_flag
, 0, MS_SHARED
))
234 if (context
->private_tmp
&& runtime
&& runtime
->shared
&& (runtime
->shared
->tmp_dir
|| runtime
->shared
->var_tmp_dir
))
237 if (context
->private_devices
||
238 context
->private_mounts
> 0 ||
239 (context
->private_mounts
< 0 && exec_needs_network_namespace(context
)) ||
240 context
->protect_system
!= PROTECT_SYSTEM_NO
||
241 context
->protect_home
!= PROTECT_HOME_NO
||
242 context
->protect_kernel_tunables
||
243 context
->protect_kernel_modules
||
244 context
->protect_kernel_logs
||
245 context
->protect_control_groups
||
246 context
->protect_proc
!= PROTECT_PROC_DEFAULT
||
247 context
->proc_subset
!= PROC_SUBSET_ALL
||
248 exec_needs_ipc_namespace(context
))
251 if (context
->root_directory
) {
252 if (exec_context_get_effective_mount_apivfs(context
))
255 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++) {
256 if (params
&& !params
->prefix
[t
])
259 if (context
->directories
[t
].n_items
> 0)
264 if (context
->dynamic_user
&&
265 (context
->directories
[EXEC_DIRECTORY_STATE
].n_items
> 0 ||
266 context
->directories
[EXEC_DIRECTORY_CACHE
].n_items
> 0 ||
267 context
->directories
[EXEC_DIRECTORY_LOGS
].n_items
> 0))
270 if (context
->log_namespace
)
276 bool exec_directory_is_private(const ExecContext
*context
, ExecDirectoryType type
) {
279 if (!context
->dynamic_user
)
282 if (type
== EXEC_DIRECTORY_CONFIGURATION
)
285 if (type
== EXEC_DIRECTORY_RUNTIME
&& context
->runtime_directory_preserve_mode
== EXEC_PRESERVE_NO
)
291 int exec_params_get_cgroup_path(
292 const ExecParameters
*params
,
293 const CGroupContext
*c
,
296 const char *subgroup
= NULL
;
302 if (!params
->cgroup_path
)
305 /* If we are called for a unit where cgroup delegation is on, and the payload created its own populated
306 * subcgroup (which we expect it to do, after all it asked for delegation), then we cannot place the control
307 * processes started after the main unit's process in the unit's main cgroup because it is now an inner one,
308 * and inner cgroups may not contain processes. Hence, if delegation is on, and this is a control process,
309 * let's use ".control" as subcgroup instead. Note that we do so only for ExecStartPost=, ExecReload=,
310 * ExecStop=, ExecStopPost=, i.e. for the commands where the main process is already forked. For ExecStartPre=
311 * this is not necessary, the cgroup is still empty. We distinguish these cases with the EXEC_CONTROL_CGROUP
312 * flag, which is only passed for the former statements, not for the latter. */
314 if (FLAGS_SET(params
->flags
, EXEC_CGROUP_DELEGATE
) && (FLAGS_SET(params
->flags
, EXEC_CONTROL_CGROUP
) || c
->delegate_subgroup
)) {
315 if (FLAGS_SET(params
->flags
, EXEC_IS_CONTROL
))
316 subgroup
= ".control";
318 subgroup
= c
->delegate_subgroup
;
322 p
= path_join(params
->cgroup_path
, subgroup
);
324 p
= strdup(params
->cgroup_path
);
332 bool exec_context_get_cpu_affinity_from_numa(const ExecContext
*c
) {
335 return c
->cpu_affinity_from_numa
;
338 static void log_command_line(Unit
*unit
, const char *msg
, const char *executable
, char **argv
) {
346 _cleanup_free_
char *cmdline
= quote_command_line(argv
, SHELL_ESCAPE_EMPTY
);
348 log_unit_struct(unit
, LOG_DEBUG
,
349 "EXECUTABLE=%s", executable
,
350 LOG_UNIT_MESSAGE(unit
, "%s: %s", msg
, strnull(cmdline
)),
351 LOG_UNIT_INVOCATION_ID(unit
));
354 static int exec_context_load_environment(const Unit
*unit
, const ExecContext
*c
, char ***l
);
356 int exec_spawn(Unit
*unit
,
357 ExecCommand
*command
,
358 const ExecContext
*context
,
359 ExecParameters
*params
,
360 ExecRuntime
*runtime
,
361 const CGroupContext
*cgroup_context
,
364 char serialization_fd_number
[DECIMAL_STR_MAX(int) + 1];
365 _cleanup_free_
char *subcgroup_path
= NULL
, *max_log_levels
= NULL
, *executor_path
= NULL
;
366 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
367 _cleanup_fdset_free_ FDSet
*fdset
= NULL
;
368 _cleanup_fclose_
FILE *f
= NULL
;
369 dual_timestamp start_timestamp
;
373 assert(unit
->manager
);
374 assert(unit
->manager
->executor_fd
>= 0);
378 assert(!params
->fds
|| FLAGS_SET(params
->flags
, EXEC_PASS_FDS
));
379 assert(params
->fds
|| (params
->n_socket_fds
+ params
->n_storage_fds
== 0));
380 assert(!params
->files_env
); /* We fill this field, ensure it comes NULL-initialized to us */
383 LOG_CONTEXT_PUSH_UNIT(unit
);
385 r
= exec_context_load_environment(unit
, context
, ¶ms
->files_env
);
387 return log_unit_error_errno(unit
, r
, "Failed to load environment files: %m");
389 /* We won't know the real executable path until we create the mount namespace in the child, but we
390 want to log from the parent, so we use the possibly inaccurate path here. */
391 log_command_line(unit
, "About to execute", command
->path
, command
->argv
);
393 if (params
->cgroup_path
) {
394 r
= exec_params_get_cgroup_path(params
, cgroup_context
, &subcgroup_path
);
396 return log_unit_error_errno(unit
, r
, "Failed to acquire subcgroup path: %m");
398 /* If there's a subcgroup, then let's create it here now (the main cgroup was already
399 * realized by the unit logic) */
401 r
= cg_create(SYSTEMD_CGROUP_CONTROLLER
, subcgroup_path
);
403 return log_unit_error_errno(unit
, r
, "Failed to create subcgroup '%s': %m", subcgroup_path
);
407 /* In order to avoid copy-on-write traps and OOM-kills when pid1's memory.current is above the
408 * child's memory.max, serialize all the state needed to start the unit, and pass it to the
409 * systemd-executor binary. clone() with CLONE_VM + CLONE_VFORK will pause the parent until the exec
410 * and ensure all memory is shared. The child immediately execs the new binary so the delay should
411 * be minimal. If glibc 2.39 is available pidfd_spawn() is used in order to get a race-free pid fd
412 * and to clone directly into the target cgroup (if we booted with cgroupv2). */
414 r
= open_serialization_file("sd-executor-state", &f
);
416 return log_unit_error_errno(unit
, r
, "Failed to open serialization stream: %m");
422 r
= exec_serialize_invocation(f
, fdset
, context
, command
, params
, runtime
, cgroup_context
);
424 return log_unit_error_errno(unit
, r
, "Failed to serialize parameters: %m");
426 if (fseeko(f
, 0, SEEK_SET
) < 0)
427 return log_unit_error_errno(unit
, errno
, "Failed to reseek on serialization stream: %m");
429 r
= fd_cloexec(fileno(f
), false);
431 return log_unit_error_errno(unit
, r
, "Failed to set O_CLOEXEC on serialization fd: %m");
433 r
= fdset_cloexec(fdset
, false);
435 return log_unit_error_errno(unit
, r
, "Failed to set O_CLOEXEC on serialized fds: %m");
437 /* If LogLevelMax= is specified, then let's use the specified log level at the beginning of the
438 * executor process. To achieve that the specified log level is passed as an argument, rather than
439 * the one for the manager process. */
440 r
= log_max_levels_to_string(context
->log_level_max
>= 0 ? context
->log_level_max
: log_get_max_level(), &max_log_levels
);
442 return log_unit_error_errno(unit
, r
, "Failed to convert max log levels to string: %m");
444 r
= fd_get_path(unit
->manager
->executor_fd
, &executor_path
);
446 return log_unit_error_errno(unit
, r
, "Failed to get executor path from fd: %m");
448 xsprintf(serialization_fd_number
, "%i", fileno(f
));
450 /* Record the start timestamp before we fork so that it is guaranteed to be earlier than the
451 * handoff timestamp. */
452 dual_timestamp_now(&start_timestamp
);
454 /* The executor binary is pinned, to avoid compatibility problems during upgrades. */
455 r
= posix_spawn_wrapper(
456 FORMAT_PROC_FD_PATH(unit
->manager
->executor_fd
),
457 STRV_MAKE(executor_path
,
458 "--deserialize", serialization_fd_number
,
459 "--log-level", max_log_levels
,
460 "--log-target", log_target_to_string(manager_get_executor_log_target(unit
->manager
))),
462 cg_unified() > 0 ? subcgroup_path
: NULL
,
464 if (r
== -EUCLEAN
&& subcgroup_path
)
465 return log_unit_error_errno(unit
, r
,
466 "Failed to spawn process into cgroup '%s', because the cgroup "
467 "or one of its parents or siblings is in the threaded mode.",
470 return log_unit_error_errno(unit
, r
, "Failed to spawn executor: %m");
471 /* We add the new process to the cgroup both in the child (so that we can be sure that no user code is ever
472 * executed outside of the cgroup) and in the parent (so that we can be sure that when we kill the cgroup the
473 * process will be killed too). */
474 if (r
== 0 && subcgroup_path
)
475 (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER
, subcgroup_path
, pidref
.pid
);
476 /* r > 0: Already in the right cgroup thanks to CLONE_INTO_CGROUP */
478 log_unit_debug(unit
, "Forked %s as " PID_FMT
" (%s CLONE_INTO_CGROUP)",
479 command
->path
, pidref
.pid
, r
> 0 ? "via" : "without");
481 exec_status_start(&command
->exec_status
, pidref
.pid
, &start_timestamp
);
483 *ret
= TAKE_PIDREF(pidref
);
487 void exec_context_init(ExecContext
*c
) {
490 /* When initializing a bool member to 'true', make sure to serialize in execute-serialize.c using
491 * serialize_bool() instead of serialize_bool_elide(). */
495 .ioprio
= IOPRIO_DEFAULT_CLASS_AND_PRIO
,
496 .cpu_sched_policy
= SCHED_OTHER
,
497 .syslog_priority
= LOG_DAEMON
|LOG_INFO
,
498 .syslog_level_prefix
= true,
499 .ignore_sigpipe
= true,
500 .timer_slack_nsec
= NSEC_INFINITY
,
501 .personality
= PERSONALITY_INVALID
,
502 .timeout_clean_usec
= USEC_INFINITY
,
503 .capability_bounding_set
= CAP_MASK_UNSET
,
504 .restrict_namespaces
= NAMESPACE_FLAGS_INITIAL
,
507 .syscall_errno
= SECCOMP_ERROR_NUMBER_KILL
,
509 .tty_rows
= UINT_MAX
,
510 .tty_cols
= UINT_MAX
,
511 .private_mounts
= -1,
514 .set_login_environment
= -1,
517 FOREACH_ARRAY(d
, c
->directories
, _EXEC_DIRECTORY_TYPE_MAX
)
520 numa_policy_reset(&c
->numa_policy
);
522 assert_cc(NAMESPACE_FLAGS_INITIAL
!= NAMESPACE_FLAGS_ALL
);
525 void exec_context_done(ExecContext
*c
) {
528 c
->environment
= strv_free(c
->environment
);
529 c
->environment_files
= strv_free(c
->environment_files
);
530 c
->pass_environment
= strv_free(c
->pass_environment
);
531 c
->unset_environment
= strv_free(c
->unset_environment
);
533 rlimit_free_all(c
->rlimit
);
535 for (size_t l
= 0; l
< 3; l
++) {
536 c
->stdio_fdname
[l
] = mfree(c
->stdio_fdname
[l
]);
537 c
->stdio_file
[l
] = mfree(c
->stdio_file
[l
]);
540 c
->working_directory
= mfree(c
->working_directory
);
541 c
->root_directory
= mfree(c
->root_directory
);
542 c
->root_image
= mfree(c
->root_image
);
543 c
->root_image_options
= mount_options_free_all(c
->root_image_options
);
544 c
->root_hash
= mfree(c
->root_hash
);
545 c
->root_hash_size
= 0;
546 c
->root_hash_path
= mfree(c
->root_hash_path
);
547 c
->root_hash_sig
= mfree(c
->root_hash_sig
);
548 c
->root_hash_sig_size
= 0;
549 c
->root_hash_sig_path
= mfree(c
->root_hash_sig_path
);
550 c
->root_verity
= mfree(c
->root_verity
);
551 c
->extension_images
= mount_image_free_many(c
->extension_images
, &c
->n_extension_images
);
552 c
->extension_directories
= strv_free(c
->extension_directories
);
553 c
->tty_path
= mfree(c
->tty_path
);
554 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
555 c
->user
= mfree(c
->user
);
556 c
->group
= mfree(c
->group
);
558 c
->supplementary_groups
= strv_free(c
->supplementary_groups
);
560 c
->pam_name
= mfree(c
->pam_name
);
562 c
->read_only_paths
= strv_free(c
->read_only_paths
);
563 c
->read_write_paths
= strv_free(c
->read_write_paths
);
564 c
->inaccessible_paths
= strv_free(c
->inaccessible_paths
);
565 c
->exec_paths
= strv_free(c
->exec_paths
);
566 c
->no_exec_paths
= strv_free(c
->no_exec_paths
);
567 c
->exec_search_path
= strv_free(c
->exec_search_path
);
569 bind_mount_free_many(c
->bind_mounts
, c
->n_bind_mounts
);
570 c
->bind_mounts
= NULL
;
571 c
->n_bind_mounts
= 0;
572 temporary_filesystem_free_many(c
->temporary_filesystems
, c
->n_temporary_filesystems
);
573 c
->temporary_filesystems
= NULL
;
574 c
->n_temporary_filesystems
= 0;
575 c
->mount_images
= mount_image_free_many(c
->mount_images
, &c
->n_mount_images
);
577 cpu_set_reset(&c
->cpu_set
);
578 numa_policy_reset(&c
->numa_policy
);
580 c
->utmp_id
= mfree(c
->utmp_id
);
581 c
->selinux_context
= mfree(c
->selinux_context
);
582 c
->apparmor_profile
= mfree(c
->apparmor_profile
);
583 c
->smack_process_label
= mfree(c
->smack_process_label
);
585 c
->restrict_filesystems
= set_free_free(c
->restrict_filesystems
);
587 c
->syscall_filter
= hashmap_free(c
->syscall_filter
);
588 c
->syscall_archs
= set_free(c
->syscall_archs
);
589 c
->address_families
= set_free(c
->address_families
);
591 FOREACH_ARRAY(d
, c
->directories
, _EXEC_DIRECTORY_TYPE_MAX
)
592 exec_directory_done(d
);
594 c
->log_level_max
= -1;
596 exec_context_free_log_extra_fields(c
);
597 c
->log_filter_allowed_patterns
= set_free_free(c
->log_filter_allowed_patterns
);
598 c
->log_filter_denied_patterns
= set_free_free(c
->log_filter_denied_patterns
);
600 c
->log_ratelimit_interval_usec
= 0;
601 c
->log_ratelimit_burst
= 0;
603 c
->stdin_data
= mfree(c
->stdin_data
);
604 c
->stdin_data_size
= 0;
606 c
->network_namespace_path
= mfree(c
->network_namespace_path
);
607 c
->ipc_namespace_path
= mfree(c
->ipc_namespace_path
);
609 c
->log_namespace
= mfree(c
->log_namespace
);
611 c
->load_credentials
= hashmap_free(c
->load_credentials
);
612 c
->set_credentials
= hashmap_free(c
->set_credentials
);
613 c
->import_credentials
= set_free_free(c
->import_credentials
);
615 c
->root_image_policy
= image_policy_free(c
->root_image_policy
);
616 c
->mount_image_policy
= image_policy_free(c
->mount_image_policy
);
617 c
->extension_image_policy
= image_policy_free(c
->extension_image_policy
);
620 int exec_context_destroy_runtime_directory(const ExecContext
*c
, const char *runtime_prefix
) {
626 FOREACH_ARRAY(i
, c
->directories
[EXEC_DIRECTORY_RUNTIME
].items
, c
->directories
[EXEC_DIRECTORY_RUNTIME
].n_items
) {
627 _cleanup_free_
char *p
= NULL
;
629 if (exec_directory_is_private(c
, EXEC_DIRECTORY_RUNTIME
))
630 p
= path_join(runtime_prefix
, "private", i
->path
);
632 p
= path_join(runtime_prefix
, i
->path
);
636 /* We execute this synchronously, since we need to be sure this is gone when we start the
638 (void) rm_rf(p
, REMOVE_ROOT
);
640 STRV_FOREACH(symlink
, i
->symlinks
) {
641 _cleanup_free_
char *symlink_abs
= NULL
;
643 if (exec_directory_is_private(c
, EXEC_DIRECTORY_RUNTIME
))
644 symlink_abs
= path_join(runtime_prefix
, "private", *symlink
);
646 symlink_abs
= path_join(runtime_prefix
, *symlink
);
650 (void) unlink(symlink_abs
);
657 int exec_context_destroy_mount_ns_dir(Unit
*u
) {
658 _cleanup_free_
char *p
= NULL
;
660 if (!u
|| !MANAGER_IS_SYSTEM(u
->manager
))
663 p
= path_join("/run/systemd/propagate/", u
->id
);
667 /* This is only filled transiently (see mount_in_namespace()), should be empty or even non-existent*/
668 if (rmdir(p
) < 0 && errno
!= ENOENT
)
669 log_unit_debug_errno(u
, errno
, "Unable to remove propagation dir '%s', ignoring: %m", p
);
674 void exec_command_done(ExecCommand
*c
) {
677 c
->path
= mfree(c
->path
);
678 c
->argv
= strv_free(c
->argv
);
681 void exec_command_done_array(ExecCommand
*c
, size_t n
) {
682 FOREACH_ARRAY(i
, c
, n
)
683 exec_command_done(i
);
686 ExecCommand
* exec_command_free(ExecCommand
*c
) {
690 exec_command_done(c
);
694 ExecCommand
* exec_command_free_list(ExecCommand
*c
) {
697 while ((i
= LIST_POP(command
, c
)))
698 exec_command_free(i
);
703 void exec_command_free_array(ExecCommand
**c
, size_t n
) {
704 FOREACH_ARRAY(i
, c
, n
)
705 *i
= exec_command_free_list(*i
);
708 void exec_command_reset_status_array(ExecCommand
*c
, size_t n
) {
709 FOREACH_ARRAY(i
, c
, n
)
710 exec_status_reset(&i
->exec_status
);
713 void exec_command_reset_status_list_array(ExecCommand
**c
, size_t n
) {
714 FOREACH_ARRAY(i
, c
, n
)
715 LIST_FOREACH(command
, z
, *i
)
716 exec_status_reset(&z
->exec_status
);
719 typedef struct InvalidEnvInfo
{
724 static void invalid_env(const char *p
, void *userdata
) {
725 InvalidEnvInfo
*info
= userdata
;
727 log_unit_error(info
->unit
, "Ignoring invalid environment assignment '%s': %s", p
, info
->path
);
730 const char* exec_context_fdname(const ExecContext
*c
, int fd_index
) {
736 if (c
->std_input
!= EXEC_INPUT_NAMED_FD
)
739 return c
->stdio_fdname
[STDIN_FILENO
] ?: "stdin";
742 if (c
->std_output
!= EXEC_OUTPUT_NAMED_FD
)
745 return c
->stdio_fdname
[STDOUT_FILENO
] ?: "stdout";
748 if (c
->std_error
!= EXEC_OUTPUT_NAMED_FD
)
751 return c
->stdio_fdname
[STDERR_FILENO
] ?: "stderr";
758 static int exec_context_load_environment(const Unit
*unit
, const ExecContext
*c
, char ***ret
) {
759 _cleanup_strv_free_
char **v
= NULL
;
765 STRV_FOREACH(i
, c
->environment_files
) {
766 _cleanup_globfree_ glob_t pglob
= {};
775 if (!path_is_absolute(fn
)) {
781 /* Filename supports globbing, take all matching files */
782 r
= safe_glob(fn
, 0, &pglob
);
789 /* When we don't match anything, -ENOENT should be returned */
790 assert(pglob
.gl_pathc
> 0);
792 FOREACH_ARRAY(path
, pglob
.gl_pathv
, pglob
.gl_pathc
) {
793 _cleanup_strv_free_
char **p
= NULL
;
795 r
= load_env_file(NULL
, *path
, &p
);
802 /* Log invalid environment variables with filename */
804 InvalidEnvInfo info
= {
809 p
= strv_env_clean_with_callback(p
, invalid_env
, &info
);
815 char **m
= strv_env_merge(v
, p
);
819 strv_free_and_replace(v
, m
);
829 static bool tty_may_match_dev_console(const char *tty
) {
830 _cleanup_free_
char *resolved
= NULL
;
835 tty
= skip_dev_prefix(tty
);
837 /* trivial identity? */
838 if (streq(tty
, "console"))
841 if (resolve_dev_console(&resolved
) < 0)
842 return true; /* if we could not resolve, assume it may */
844 /* "tty0" means the active VC, so it may be the same sometimes */
845 return path_equal(resolved
, tty
) || (streq(resolved
, "tty0") && tty_is_vc(tty
));
848 static bool exec_context_may_touch_tty(const ExecContext
*ec
) {
851 return ec
->tty_reset
||
853 ec
->tty_vt_disallocate
||
854 is_terminal_input(ec
->std_input
) ||
855 is_terminal_output(ec
->std_output
) ||
856 is_terminal_output(ec
->std_error
);
859 bool exec_context_may_touch_console(const ExecContext
*ec
) {
861 return exec_context_may_touch_tty(ec
) &&
862 tty_may_match_dev_console(exec_context_tty_path(ec
));
865 static void strv_fprintf(FILE *f
, char **l
) {
869 fprintf(f
, " %s", *g
);
872 static void strv_dump(FILE* f
, const char *prefix
, const char *name
, char **strv
) {
877 if (!strv_isempty(strv
)) {
878 fprintf(f
, "%s%s:", prefix
, name
);
879 strv_fprintf(f
, strv
);
884 void exec_params_dump(const ExecParameters
*p
, FILE* f
, const char *prefix
) {
888 prefix
= strempty(prefix
);
891 "%sRuntimeScope: %s\n"
893 "%sSELinuxContextNetwork: %s\n"
894 "%sCgroupSupportedMask: %u\n"
896 "%sCrededentialsDirectory: %s\n"
897 "%sEncryptedCredentialsDirectory: %s\n"
898 "%sConfirmSpawn: %s\n"
899 "%sShallConfirmSpawn: %s\n"
900 "%sWatchdogUSec: " USEC_FMT
"\n"
901 "%sNotifySocket: %s\n"
902 "%sFallbackSmackProcessLabel: %s\n",
903 prefix
, runtime_scope_to_string(p
->runtime_scope
),
905 prefix
, yes_no(p
->selinux_context_net
),
906 prefix
, p
->cgroup_supported
,
907 prefix
, p
->cgroup_path
,
908 prefix
, strempty(p
->received_credentials_directory
),
909 prefix
, strempty(p
->received_encrypted_credentials_directory
),
910 prefix
, strempty(p
->confirm_spawn
),
911 prefix
, yes_no(p
->shall_confirm_spawn
),
912 prefix
, p
->watchdog_usec
,
913 prefix
, strempty(p
->notify_socket
),
914 prefix
, strempty(p
->fallback_smack_process_label
));
916 strv_dump(f
, prefix
, "FdNames", p
->fd_names
);
917 strv_dump(f
, prefix
, "Environment", p
->environment
);
918 strv_dump(f
, prefix
, "Prefix", p
->prefix
);
920 LIST_FOREACH(open_files
, file
, p
->open_files
)
921 fprintf(f
, "%sOpenFile: %s %s", prefix
, file
->path
, open_file_flags_to_string(file
->flags
));
923 strv_dump(f
, prefix
, "FilesEnv", p
->files_env
);
926 void exec_context_dump(const ExecContext
*c
, FILE* f
, const char *prefix
) {
932 prefix
= strempty(prefix
);
936 "%sWorkingDirectory: %s\n"
937 "%sRootDirectory: %s\n"
938 "%sRootEphemeral: %s\n"
939 "%sNonBlocking: %s\n"
941 "%sPrivateDevices: %s\n"
942 "%sProtectKernelTunables: %s\n"
943 "%sProtectKernelModules: %s\n"
944 "%sProtectKernelLogs: %s\n"
945 "%sProtectClock: %s\n"
946 "%sProtectControlGroups: %s\n"
947 "%sPrivateNetwork: %s\n"
948 "%sPrivateUsers: %s\n"
949 "%sProtectHome: %s\n"
950 "%sProtectSystem: %s\n"
951 "%sMountAPIVFS: %s\n"
952 "%sIgnoreSIGPIPE: %s\n"
953 "%sMemoryDenyWriteExecute: %s\n"
954 "%sRestrictRealtime: %s\n"
955 "%sRestrictSUIDSGID: %s\n"
956 "%sKeyringMode: %s\n"
957 "%sProtectHostname: %s\n"
958 "%sProtectProc: %s\n"
959 "%sProcSubset: %s\n",
961 prefix
, empty_to_root(c
->working_directory
),
962 prefix
, empty_to_root(c
->root_directory
),
963 prefix
, yes_no(c
->root_ephemeral
),
964 prefix
, yes_no(c
->non_blocking
),
965 prefix
, yes_no(c
->private_tmp
),
966 prefix
, yes_no(c
->private_devices
),
967 prefix
, yes_no(c
->protect_kernel_tunables
),
968 prefix
, yes_no(c
->protect_kernel_modules
),
969 prefix
, yes_no(c
->protect_kernel_logs
),
970 prefix
, yes_no(c
->protect_clock
),
971 prefix
, yes_no(c
->protect_control_groups
),
972 prefix
, yes_no(c
->private_network
),
973 prefix
, yes_no(c
->private_users
),
974 prefix
, protect_home_to_string(c
->protect_home
),
975 prefix
, protect_system_to_string(c
->protect_system
),
976 prefix
, yes_no(exec_context_get_effective_mount_apivfs(c
)),
977 prefix
, yes_no(c
->ignore_sigpipe
),
978 prefix
, yes_no(c
->memory_deny_write_execute
),
979 prefix
, yes_no(c
->restrict_realtime
),
980 prefix
, yes_no(c
->restrict_suid_sgid
),
981 prefix
, exec_keyring_mode_to_string(c
->keyring_mode
),
982 prefix
, yes_no(c
->protect_hostname
),
983 prefix
, protect_proc_to_string(c
->protect_proc
),
984 prefix
, proc_subset_to_string(c
->proc_subset
));
986 if (c
->set_login_environment
>= 0)
987 fprintf(f
, "%sSetLoginEnvironment: %s\n", prefix
, yes_no(c
->set_login_environment
> 0));
990 fprintf(f
, "%sRootImage: %s\n", prefix
, c
->root_image
);
992 if (c
->root_image_options
) {
993 fprintf(f
, "%sRootImageOptions:", prefix
);
994 LIST_FOREACH(mount_options
, o
, c
->root_image_options
)
995 if (!isempty(o
->options
))
997 partition_designator_to_string(o
->partition_designator
),
1003 _cleanup_free_
char *encoded
= NULL
;
1004 encoded
= hexmem(c
->root_hash
, c
->root_hash_size
);
1006 fprintf(f
, "%sRootHash: %s\n", prefix
, encoded
);
1009 if (c
->root_hash_path
)
1010 fprintf(f
, "%sRootHash: %s\n", prefix
, c
->root_hash_path
);
1012 if (c
->root_hash_sig
) {
1013 _cleanup_free_
char *encoded
= NULL
;
1015 len
= base64mem(c
->root_hash_sig
, c
->root_hash_sig_size
, &encoded
);
1017 fprintf(f
, "%sRootHashSignature: base64:%s\n", prefix
, encoded
);
1020 if (c
->root_hash_sig_path
)
1021 fprintf(f
, "%sRootHashSignature: %s\n", prefix
, c
->root_hash_sig_path
);
1024 fprintf(f
, "%sRootVerity: %s\n", prefix
, c
->root_verity
);
1026 STRV_FOREACH(e
, c
->environment
)
1027 fprintf(f
, "%sEnvironment: %s\n", prefix
, *e
);
1029 STRV_FOREACH(e
, c
->environment_files
)
1030 fprintf(f
, "%sEnvironmentFile: %s\n", prefix
, *e
);
1032 STRV_FOREACH(e
, c
->pass_environment
)
1033 fprintf(f
, "%sPassEnvironment: %s\n", prefix
, *e
);
1035 STRV_FOREACH(e
, c
->unset_environment
)
1036 fprintf(f
, "%sUnsetEnvironment: %s\n", prefix
, *e
);
1038 fprintf(f
, "%sRuntimeDirectoryPreserve: %s\n", prefix
, exec_preserve_mode_to_string(c
->runtime_directory_preserve_mode
));
1040 for (ExecDirectoryType dt
= 0; dt
< _EXEC_DIRECTORY_TYPE_MAX
; dt
++) {
1041 fprintf(f
, "%s%sMode: %04o\n", prefix
, exec_directory_type_to_string(dt
), c
->directories
[dt
].mode
);
1043 for (size_t i
= 0; i
< c
->directories
[dt
].n_items
; i
++) {
1044 fprintf(f
, "%s%s: %s\n", prefix
, exec_directory_type_to_string(dt
), c
->directories
[dt
].items
[i
].path
);
1046 STRV_FOREACH(d
, c
->directories
[dt
].items
[i
].symlinks
)
1047 fprintf(f
, "%s%s: %s:%s\n", prefix
, exec_directory_type_symlink_to_string(dt
), c
->directories
[dt
].items
[i
].path
, *d
);
1051 fprintf(f
, "%sTimeoutCleanSec: %s\n", prefix
, FORMAT_TIMESPAN(c
->timeout_clean_usec
, USEC_PER_SEC
));
1053 if (c
->memory_ksm
>= 0)
1054 fprintf(f
, "%sMemoryKSM: %s\n", prefix
, yes_no(c
->memory_ksm
> 0));
1057 fprintf(f
, "%sNice: %i\n", prefix
, c
->nice
);
1059 if (c
->oom_score_adjust_set
)
1060 fprintf(f
, "%sOOMScoreAdjust: %i\n", prefix
, c
->oom_score_adjust
);
1062 if (c
->coredump_filter_set
)
1063 fprintf(f
, "%sCoredumpFilter: 0x%"PRIx64
"\n", prefix
, c
->coredump_filter
);
1065 for (unsigned i
= 0; i
< RLIM_NLIMITS
; i
++)
1067 fprintf(f
, "%sLimit%s: " RLIM_FMT
"\n",
1068 prefix
, rlimit_to_string(i
), c
->rlimit
[i
]->rlim_max
);
1069 fprintf(f
, "%sLimit%sSoft: " RLIM_FMT
"\n",
1070 prefix
, rlimit_to_string(i
), c
->rlimit
[i
]->rlim_cur
);
1073 if (c
->ioprio_set
) {
1074 _cleanup_free_
char *class_str
= NULL
;
1076 r
= ioprio_class_to_string_alloc(ioprio_prio_class(c
->ioprio
), &class_str
);
1078 fprintf(f
, "%sIOSchedulingClass: %s\n", prefix
, class_str
);
1080 fprintf(f
, "%sIOPriority: %d\n", prefix
, ioprio_prio_data(c
->ioprio
));
1083 if (c
->cpu_sched_set
) {
1084 _cleanup_free_
char *policy_str
= NULL
;
1086 r
= sched_policy_to_string_alloc(c
->cpu_sched_policy
, &policy_str
);
1088 fprintf(f
, "%sCPUSchedulingPolicy: %s\n", prefix
, policy_str
);
1091 "%sCPUSchedulingPriority: %i\n"
1092 "%sCPUSchedulingResetOnFork: %s\n",
1093 prefix
, c
->cpu_sched_priority
,
1094 prefix
, yes_no(c
->cpu_sched_reset_on_fork
));
1097 if (c
->cpu_set
.set
) {
1098 _cleanup_free_
char *affinity
= NULL
;
1100 affinity
= cpu_set_to_range_string(&c
->cpu_set
);
1101 fprintf(f
, "%sCPUAffinity: %s\n", prefix
, affinity
);
1104 if (mpol_is_valid(numa_policy_get_type(&c
->numa_policy
))) {
1105 _cleanup_free_
char *nodes
= NULL
;
1107 nodes
= cpu_set_to_range_string(&c
->numa_policy
.nodes
);
1108 fprintf(f
, "%sNUMAPolicy: %s\n", prefix
, mpol_to_string(numa_policy_get_type(&c
->numa_policy
)));
1109 fprintf(f
, "%sNUMAMask: %s\n", prefix
, strnull(nodes
));
1112 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
1113 fprintf(f
, "%sTimerSlackNSec: "NSEC_FMT
"\n", prefix
, c
->timer_slack_nsec
);
1116 "%sStandardInput: %s\n"
1117 "%sStandardOutput: %s\n"
1118 "%sStandardError: %s\n",
1119 prefix
, exec_input_to_string(c
->std_input
),
1120 prefix
, exec_output_to_string(c
->std_output
),
1121 prefix
, exec_output_to_string(c
->std_error
));
1123 if (c
->std_input
== EXEC_INPUT_NAMED_FD
)
1124 fprintf(f
, "%sStandardInputFileDescriptorName: %s\n", prefix
, c
->stdio_fdname
[STDIN_FILENO
]);
1125 if (c
->std_output
== EXEC_OUTPUT_NAMED_FD
)
1126 fprintf(f
, "%sStandardOutputFileDescriptorName: %s\n", prefix
, c
->stdio_fdname
[STDOUT_FILENO
]);
1127 if (c
->std_error
== EXEC_OUTPUT_NAMED_FD
)
1128 fprintf(f
, "%sStandardErrorFileDescriptorName: %s\n", prefix
, c
->stdio_fdname
[STDERR_FILENO
]);
1130 if (c
->std_input
== EXEC_INPUT_FILE
)
1131 fprintf(f
, "%sStandardInputFile: %s\n", prefix
, c
->stdio_file
[STDIN_FILENO
]);
1132 if (c
->std_output
== EXEC_OUTPUT_FILE
)
1133 fprintf(f
, "%sStandardOutputFile: %s\n", prefix
, c
->stdio_file
[STDOUT_FILENO
]);
1134 if (c
->std_output
== EXEC_OUTPUT_FILE_APPEND
)
1135 fprintf(f
, "%sStandardOutputFileToAppend: %s\n", prefix
, c
->stdio_file
[STDOUT_FILENO
]);
1136 if (c
->std_output
== EXEC_OUTPUT_FILE_TRUNCATE
)
1137 fprintf(f
, "%sStandardOutputFileToTruncate: %s\n", prefix
, c
->stdio_file
[STDOUT_FILENO
]);
1138 if (c
->std_error
== EXEC_OUTPUT_FILE
)
1139 fprintf(f
, "%sStandardErrorFile: %s\n", prefix
, c
->stdio_file
[STDERR_FILENO
]);
1140 if (c
->std_error
== EXEC_OUTPUT_FILE_APPEND
)
1141 fprintf(f
, "%sStandardErrorFileToAppend: %s\n", prefix
, c
->stdio_file
[STDERR_FILENO
]);
1142 if (c
->std_error
== EXEC_OUTPUT_FILE_TRUNCATE
)
1143 fprintf(f
, "%sStandardErrorFileToTruncate: %s\n", prefix
, c
->stdio_file
[STDERR_FILENO
]);
1149 "%sTTYVHangup: %s\n"
1150 "%sTTYVTDisallocate: %s\n"
1152 "%sTTYColumns: %u\n",
1153 prefix
, c
->tty_path
,
1154 prefix
, yes_no(c
->tty_reset
),
1155 prefix
, yes_no(c
->tty_vhangup
),
1156 prefix
, yes_no(c
->tty_vt_disallocate
),
1157 prefix
, c
->tty_rows
,
1158 prefix
, c
->tty_cols
);
1160 if (IN_SET(c
->std_output
,
1162 EXEC_OUTPUT_JOURNAL
,
1163 EXEC_OUTPUT_KMSG_AND_CONSOLE
,
1164 EXEC_OUTPUT_JOURNAL_AND_CONSOLE
) ||
1165 IN_SET(c
->std_error
,
1167 EXEC_OUTPUT_JOURNAL
,
1168 EXEC_OUTPUT_KMSG_AND_CONSOLE
,
1169 EXEC_OUTPUT_JOURNAL_AND_CONSOLE
)) {
1171 _cleanup_free_
char *fac_str
= NULL
, *lvl_str
= NULL
;
1173 r
= log_facility_unshifted_to_string_alloc(c
->syslog_priority
>> 3, &fac_str
);
1175 fprintf(f
, "%sSyslogFacility: %s\n", prefix
, fac_str
);
1177 r
= log_level_to_string_alloc(LOG_PRI(c
->syslog_priority
), &lvl_str
);
1179 fprintf(f
, "%sSyslogLevel: %s\n", prefix
, lvl_str
);
1182 if (c
->log_level_max
>= 0) {
1183 _cleanup_free_
char *t
= NULL
;
1185 (void) log_level_to_string_alloc(c
->log_level_max
, &t
);
1187 fprintf(f
, "%sLogLevelMax: %s\n", prefix
, strna(t
));
1190 if (c
->log_ratelimit_interval_usec
> 0)
1192 "%sLogRateLimitIntervalSec: %s\n",
1193 prefix
, FORMAT_TIMESPAN(c
->log_ratelimit_interval_usec
, USEC_PER_SEC
));
1195 if (c
->log_ratelimit_burst
> 0)
1196 fprintf(f
, "%sLogRateLimitBurst: %u\n", prefix
, c
->log_ratelimit_burst
);
1198 if (!set_isempty(c
->log_filter_allowed_patterns
) || !set_isempty(c
->log_filter_denied_patterns
)) {
1199 fprintf(f
, "%sLogFilterPatterns:", prefix
);
1202 SET_FOREACH(pattern
, c
->log_filter_allowed_patterns
)
1203 fprintf(f
, " %s", pattern
);
1204 SET_FOREACH(pattern
, c
->log_filter_denied_patterns
)
1205 fprintf(f
, " ~%s", pattern
);
1209 FOREACH_ARRAY(field
, c
->log_extra_fields
, c
->n_log_extra_fields
) {
1210 fprintf(f
, "%sLogExtraFields: ", prefix
);
1211 fwrite(field
->iov_base
, 1, field
->iov_len
, f
);
1215 if (c
->log_namespace
)
1216 fprintf(f
, "%sLogNamespace: %s\n", prefix
, c
->log_namespace
);
1218 if (c
->secure_bits
) {
1219 _cleanup_free_
char *str
= NULL
;
1221 r
= secure_bits_to_string_alloc(c
->secure_bits
, &str
);
1223 fprintf(f
, "%sSecure Bits: %s\n", prefix
, str
);
1226 if (c
->capability_bounding_set
!= CAP_MASK_UNSET
) {
1227 _cleanup_free_
char *str
= NULL
;
1229 r
= capability_set_to_string(c
->capability_bounding_set
, &str
);
1231 fprintf(f
, "%sCapabilityBoundingSet: %s\n", prefix
, str
);
1234 if (c
->capability_ambient_set
!= 0) {
1235 _cleanup_free_
char *str
= NULL
;
1237 r
= capability_set_to_string(c
->capability_ambient_set
, &str
);
1239 fprintf(f
, "%sAmbientCapabilities: %s\n", prefix
, str
);
1243 fprintf(f
, "%sUser: %s\n", prefix
, c
->user
);
1245 fprintf(f
, "%sGroup: %s\n", prefix
, c
->group
);
1247 fprintf(f
, "%sDynamicUser: %s\n", prefix
, yes_no(c
->dynamic_user
));
1249 strv_dump(f
, prefix
, "SupplementaryGroups", c
->supplementary_groups
);
1252 fprintf(f
, "%sPAMName: %s\n", prefix
, c
->pam_name
);
1254 strv_dump(f
, prefix
, "ReadWritePaths", c
->read_write_paths
);
1255 strv_dump(f
, prefix
, "ReadOnlyPaths", c
->read_only_paths
);
1256 strv_dump(f
, prefix
, "InaccessiblePaths", c
->inaccessible_paths
);
1257 strv_dump(f
, prefix
, "ExecPaths", c
->exec_paths
);
1258 strv_dump(f
, prefix
, "NoExecPaths", c
->no_exec_paths
);
1259 strv_dump(f
, prefix
, "ExecSearchPath", c
->exec_search_path
);
1261 FOREACH_ARRAY(mount
, c
->bind_mounts
, c
->n_bind_mounts
)
1262 fprintf(f
, "%s%s: %s%s:%s:%s\n", prefix
,
1263 mount
->read_only
? "BindReadOnlyPaths" : "BindPaths",
1264 mount
->ignore_enoent
? "-": "",
1267 mount
->recursive
? "rbind" : "norbind");
1269 FOREACH_ARRAY(tmpfs
, c
->temporary_filesystems
, c
->n_temporary_filesystems
)
1270 fprintf(f
, "%sTemporaryFileSystem: %s%s%s\n", prefix
,
1272 isempty(tmpfs
->options
) ? "" : ":",
1273 strempty(tmpfs
->options
));
1277 "%sUtmpIdentifier: %s\n",
1278 prefix
, c
->utmp_id
);
1280 if (c
->selinux_context
)
1282 "%sSELinuxContext: %s%s\n",
1283 prefix
, c
->selinux_context_ignore
? "-" : "", c
->selinux_context
);
1285 if (c
->apparmor_profile
)
1287 "%sAppArmorProfile: %s%s\n",
1288 prefix
, c
->apparmor_profile_ignore
? "-" : "", c
->apparmor_profile
);
1290 if (c
->smack_process_label
)
1292 "%sSmackProcessLabel: %s%s\n",
1293 prefix
, c
->smack_process_label_ignore
? "-" : "", c
->smack_process_label
);
1295 if (c
->personality
!= PERSONALITY_INVALID
)
1297 "%sPersonality: %s\n",
1298 prefix
, strna(personality_to_string(c
->personality
)));
1301 "%sLockPersonality: %s\n",
1302 prefix
, yes_no(c
->lock_personality
));
1304 if (c
->syscall_filter
) {
1306 "%sSystemCallFilter: ",
1309 if (!c
->syscall_allow_list
)
1315 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_filter
) {
1316 _cleanup_free_
char *name
= NULL
;
1317 const char *errno_name
= NULL
;
1318 int num
= PTR_TO_INT(val
);
1325 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
1326 fputs(strna(name
), f
);
1329 errno_name
= seccomp_errno_or_action_to_string(num
);
1331 fprintf(f
, ":%s", errno_name
);
1333 fprintf(f
, ":%d", num
);
1341 if (c
->syscall_archs
) {
1343 "%sSystemCallArchitectures:",
1348 SET_FOREACH(id
, c
->syscall_archs
)
1349 fprintf(f
, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1)));
1354 if (exec_context_restrict_namespaces_set(c
)) {
1355 _cleanup_free_
char *s
= NULL
;
1357 r
= namespace_flags_to_string(c
->restrict_namespaces
, &s
);
1359 fprintf(f
, "%sRestrictNamespaces: %s\n",
1364 if (exec_context_restrict_filesystems_set(c
)) {
1366 SET_FOREACH(fs
, c
->restrict_filesystems
)
1367 fprintf(f
, "%sRestrictFileSystems: %s\n", prefix
, fs
);
1371 if (c
->network_namespace_path
)
1373 "%sNetworkNamespacePath: %s\n",
1374 prefix
, c
->network_namespace_path
);
1376 if (c
->syscall_errno
> 0) {
1377 fprintf(f
, "%sSystemCallErrorNumber: ", prefix
);
1380 const char *errno_name
= seccomp_errno_or_action_to_string(c
->syscall_errno
);
1382 fputs(errno_name
, f
);
1384 fprintf(f
, "%d", c
->syscall_errno
);
1389 FOREACH_ARRAY(mount
, c
->mount_images
, c
->n_mount_images
) {
1390 fprintf(f
, "%sMountImages: %s%s:%s", prefix
,
1391 mount
->ignore_enoent
? "-": "",
1393 mount
->destination
);
1394 LIST_FOREACH(mount_options
, o
, mount
->mount_options
)
1395 fprintf(f
, ":%s:%s",
1396 partition_designator_to_string(o
->partition_designator
),
1397 strempty(o
->options
));
1401 FOREACH_ARRAY(mount
, c
->extension_images
, c
->n_extension_images
) {
1402 fprintf(f
, "%sExtensionImages: %s%s", prefix
,
1403 mount
->ignore_enoent
? "-": "",
1405 LIST_FOREACH(mount_options
, o
, mount
->mount_options
)
1406 fprintf(f
, ":%s:%s",
1407 partition_designator_to_string(o
->partition_designator
),
1408 strempty(o
->options
));
1412 strv_dump(f
, prefix
, "ExtensionDirectories", c
->extension_directories
);
1415 bool exec_context_maintains_privileges(const ExecContext
*c
) {
1418 /* Returns true if the process forked off would run under
1419 * an unchanged UID or as root. */
1424 if (STR_IN_SET(c
->user
, "root", "0"))
1430 int exec_context_get_effective_ioprio(const ExecContext
*c
) {
1438 p
= ioprio_get(IOPRIO_WHO_PROCESS
, 0);
1440 return IOPRIO_DEFAULT_CLASS_AND_PRIO
;
1442 return ioprio_normalize(p
);
1445 bool exec_context_get_effective_mount_apivfs(const ExecContext
*c
) {
1448 /* Explicit setting wins */
1449 if (c
->mount_apivfs
>= 0)
1450 return c
->mount_apivfs
> 0;
1452 /* Default to "yes" if root directory or image are specified */
1453 if (exec_context_with_rootfs(c
))
1459 void exec_context_free_log_extra_fields(ExecContext
*c
) {
1462 FOREACH_ARRAY(field
, c
->log_extra_fields
, c
->n_log_extra_fields
)
1463 free(field
->iov_base
);
1465 c
->log_extra_fields
= mfree(c
->log_extra_fields
);
1466 c
->n_log_extra_fields
= 0;
1469 void exec_context_revert_tty(ExecContext
*c
) {
1470 _cleanup_close_
int fd
= -EBADF
;
1477 /* First, reset the TTY (possibly kicking everybody else from the TTY) */
1478 exec_context_tty_reset(c
, /* parameters= */ NULL
);
1480 /* And then undo what chown_terminal() did earlier. Note that we only do this if we have a path
1481 * configured. If the TTY was passed to us as file descriptor we assume the TTY is opened and managed
1482 * by whoever passed it to us and thus knows better when and how to chmod()/chown() it back. */
1483 if (!exec_context_may_touch_tty(c
))
1486 path
= exec_context_tty_path(c
);
1490 fd
= open(path
, O_PATH
|O_CLOEXEC
); /* Pin the inode */
1492 return (void) log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_WARNING
, errno
,
1493 "Failed to open TTY inode of '%s' to adjust ownership/access mode, ignoring: %m",
1496 if (fstat(fd
, &st
) < 0)
1497 return (void) log_warning_errno(errno
, "Failed to stat TTY '%s', ignoring: %m", path
);
1499 /* Let's add a superficial check that we only do this for stuff that looks like a TTY. We only check
1500 * if things are a character device, since a proper check either means we'd have to open the TTY and
1501 * use isatty(), but we'd rather not do that since opening TTYs comes with all kinds of side-effects
1502 * and is slow. Or we'd have to hardcode dev_t major information, which we'd rather avoid. Why bother
1503 * with this at all? → https://github.com/systemd/systemd/issues/19213 */
1504 if (!S_ISCHR(st
.st_mode
))
1505 return log_warning("Configured TTY '%s' is not actually a character device, ignoring.", path
);
1507 r
= fchmod_and_chown(fd
, TTY_MODE
, 0, TTY_GID
);
1509 log_warning_errno(r
, "Failed to reset TTY ownership/access mode of %s to " UID_FMT
":" GID_FMT
", ignoring: %m", path
, (uid_t
) 0, (gid_t
) TTY_GID
);
1512 int exec_context_get_clean_directories(
1518 _cleanup_strv_free_
char **l
= NULL
;
1525 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++) {
1526 if (!FLAGS_SET(mask
, 1U << t
))
1532 FOREACH_ARRAY(i
, c
->directories
[t
].items
, c
->directories
[t
].n_items
) {
1535 j
= path_join(prefix
[t
], i
->path
);
1539 r
= strv_consume(&l
, j
);
1543 /* Also remove private directories unconditionally. */
1544 if (t
!= EXEC_DIRECTORY_CONFIGURATION
) {
1545 j
= path_join(prefix
[t
], "private", i
->path
);
1549 r
= strv_consume(&l
, j
);
1554 STRV_FOREACH(symlink
, i
->symlinks
) {
1555 j
= path_join(prefix
[t
], *symlink
);
1559 r
= strv_consume(&l
, j
);
1570 int exec_context_get_clean_mask(ExecContext
*c
, ExecCleanMask
*ret
) {
1571 ExecCleanMask mask
= 0;
1576 for (ExecDirectoryType t
= 0; t
< _EXEC_DIRECTORY_TYPE_MAX
; t
++)
1577 if (c
->directories
[t
].n_items
> 0)
1584 int exec_context_get_oom_score_adjust(const ExecContext
*c
) {
1589 if (c
->oom_score_adjust_set
)
1590 return c
->oom_score_adjust
;
1592 r
= get_oom_score_adjust(&n
);
1594 log_debug_errno(r
, "Failed to read /proc/self/oom_score_adj, ignoring: %m");
1599 uint64_t exec_context_get_coredump_filter(const ExecContext
*c
) {
1600 _cleanup_free_
char *t
= NULL
;
1601 uint64_t n
= COREDUMP_FILTER_MASK_DEFAULT
;
1606 if (c
->coredump_filter_set
)
1607 return c
->coredump_filter
;
1609 r
= read_one_line_file("/proc/self/coredump_filter", &t
);
1611 log_debug_errno(r
, "Failed to read /proc/self/coredump_filter, ignoring: %m");
1613 r
= safe_atoux64(t
, &n
);
1615 log_debug_errno(r
, "Failed to parse \"%s\" from /proc/self/coredump_filter, ignoring: %m", t
);
1621 int exec_context_get_nice(const ExecContext
*c
) {
1630 n
= getpriority(PRIO_PROCESS
, 0);
1632 log_debug_errno(errno
, "Failed to get process nice value, ignoring: %m");
1639 int exec_context_get_cpu_sched_policy(const ExecContext
*c
) {
1644 if (c
->cpu_sched_set
)
1645 return c
->cpu_sched_policy
;
1647 n
= sched_getscheduler(0);
1649 log_debug_errno(errno
, "Failed to get scheduler policy, ignoring: %m");
1651 return n
< 0 ? SCHED_OTHER
: n
;
1654 int exec_context_get_cpu_sched_priority(const ExecContext
*c
) {
1655 struct sched_param p
= {};
1660 if (c
->cpu_sched_set
)
1661 return c
->cpu_sched_priority
;
1663 r
= sched_getparam(0, &p
);
1665 log_debug_errno(errno
, "Failed to get scheduler priority, ignoring: %m");
1667 return r
>= 0 ? p
.sched_priority
: 0;
1670 uint64_t exec_context_get_timer_slack_nsec(const ExecContext
*c
) {
1675 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
1676 return c
->timer_slack_nsec
;
1678 r
= prctl(PR_GET_TIMERSLACK
);
1680 log_debug_errno(r
, "Failed to get timer slack, ignoring: %m");
1682 return (uint64_t) MAX(r
, 0);
1685 bool exec_context_get_set_login_environment(const ExecContext
*c
) {
1688 if (c
->set_login_environment
>= 0)
1689 return c
->set_login_environment
;
1691 return c
->user
|| c
->dynamic_user
|| c
->pam_name
;
1694 char** exec_context_get_syscall_filter(const ExecContext
*c
) {
1695 _cleanup_strv_free_
char **l
= NULL
;
1701 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_filter
) {
1702 _cleanup_free_
char *name
= NULL
;
1703 const char *e
= NULL
;
1705 int num
= PTR_TO_INT(val
);
1707 if (c
->syscall_allow_list
&& num
>= 0)
1708 /* syscall with num >= 0 in allow-list is denied. */
1711 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
1716 e
= seccomp_errno_or_action_to_string(num
);
1718 s
= strjoin(name
, ":", e
);
1722 if (asprintf(&s
, "%s:%d", name
, num
) < 0)
1728 if (strv_consume(&l
, s
) < 0)
1735 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1738 char** exec_context_get_syscall_archs(const ExecContext
*c
) {
1739 _cleanup_strv_free_
char **l
= NULL
;
1745 SET_FOREACH(id
, c
->syscall_archs
) {
1748 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
1752 if (strv_extend(&l
, name
) < 0)
1759 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1762 char** exec_context_get_syscall_log(const ExecContext
*c
) {
1763 _cleanup_strv_free_
char **l
= NULL
;
1769 HASHMAP_FOREACH_KEY(val
, id
, c
->syscall_log
) {
1772 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
1776 if (strv_consume(&l
, name
) < 0)
1783 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1786 char** exec_context_get_address_families(const ExecContext
*c
) {
1787 _cleanup_strv_free_
char **l
= NULL
;
1792 SET_FOREACH(af
, c
->address_families
) {
1795 name
= af_to_name(PTR_TO_INT(af
));
1799 if (strv_extend(&l
, name
) < 0)
1805 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1808 char** exec_context_get_restrict_filesystems(const ExecContext
*c
) {
1809 _cleanup_strv_free_
char **l
= NULL
;
1814 l
= set_get_strv(c
->restrict_filesystems
);
1821 return l
? TAKE_PTR(l
) : strv_new(NULL
);
1824 void exec_status_start(ExecStatus
*s
, pid_t pid
, const dual_timestamp
*ts
) {
1832 s
->start_timestamp
= *ts
;
1834 dual_timestamp_now(&s
->start_timestamp
);
1837 void exec_status_exit(ExecStatus
*s
, const ExecContext
*context
, pid_t pid
, int code
, int status
) {
1845 dual_timestamp_now(&s
->exit_timestamp
);
1850 if (context
&& context
->utmp_id
)
1851 (void) utmp_put_dead_process(context
->utmp_id
, pid
, code
, status
);
1854 void exec_status_handoff(ExecStatus
*s
, const struct ucred
*ucred
, const dual_timestamp
*ts
) {
1859 if (ucred
->pid
!= s
->pid
)
1864 s
->handoff_timestamp
= *ts
;
1867 void exec_status_reset(ExecStatus
*s
) {
1870 *s
= (ExecStatus
) {};
1873 void exec_status_dump(const ExecStatus
*s
, FILE *f
, const char *prefix
) {
1880 prefix
= strempty(prefix
);
1883 "%sPID: "PID_FMT
"\n",
1886 if (dual_timestamp_is_set(&s
->start_timestamp
))
1888 "%sStart Timestamp: %s\n",
1889 prefix
, FORMAT_TIMESTAMP_STYLE(s
->start_timestamp
.realtime
, TIMESTAMP_US
));
1891 if (dual_timestamp_is_set(&s
->handoff_timestamp
) && dual_timestamp_is_set(&s
->start_timestamp
) &&
1892 s
->handoff_timestamp
.monotonic
> s
->start_timestamp
.monotonic
)
1894 "%sHandoff Timestamp: %s since start\n",
1896 FORMAT_TIMESPAN(usec_sub_unsigned(s
->handoff_timestamp
.monotonic
, s
->start_timestamp
.monotonic
), 1));
1899 "%sHandoff Timestamp: %s\n",
1900 prefix
, FORMAT_TIMESTAMP_STYLE(s
->handoff_timestamp
.realtime
, TIMESTAMP_US
));
1902 if (dual_timestamp_is_set(&s
->exit_timestamp
)) {
1904 if (dual_timestamp_is_set(&s
->handoff_timestamp
) && s
->exit_timestamp
.monotonic
> s
->handoff_timestamp
.monotonic
)
1906 "%sExit Timestamp: %s since handoff\n",
1908 FORMAT_TIMESPAN(usec_sub_unsigned(s
->exit_timestamp
.monotonic
, s
->handoff_timestamp
.monotonic
), 1));
1909 else if (dual_timestamp_is_set(&s
->start_timestamp
) && s
->exit_timestamp
.monotonic
> s
->start_timestamp
.monotonic
)
1911 "%sExit Timestamp: %s since start\n",
1913 FORMAT_TIMESPAN(usec_sub_unsigned(s
->exit_timestamp
.monotonic
, s
->start_timestamp
.monotonic
), 1));
1916 "%sExit Timestamp: %s\n",
1917 prefix
, FORMAT_TIMESTAMP_STYLE(s
->exit_timestamp
.realtime
, TIMESTAMP_US
));
1921 "%sExit Status: %i\n",
1922 prefix
, sigchld_code_to_string(s
->code
),
1927 void exec_command_dump(ExecCommand
*c
, FILE *f
, const char *prefix
) {
1928 _cleanup_free_
char *cmd
= NULL
;
1929 const char *prefix2
;
1934 prefix
= strempty(prefix
);
1935 prefix2
= strjoina(prefix
, "\t");
1937 cmd
= quote_command_line(c
->argv
, SHELL_ESCAPE_EMPTY
);
1940 "%sCommand Line: %s\n",
1941 prefix
, strnull(cmd
));
1943 exec_status_dump(&c
->exec_status
, f
, prefix2
);
1946 void exec_command_dump_list(ExecCommand
*c
, FILE *f
, const char *prefix
) {
1949 prefix
= strempty(prefix
);
1951 LIST_FOREACH(command
, i
, c
)
1952 exec_command_dump(i
, f
, prefix
);
1955 void exec_command_append_list(ExecCommand
**l
, ExecCommand
*e
) {
1962 /* It's kind of important, that we keep the order here */
1963 end
= LIST_FIND_TAIL(command
, *l
);
1964 LIST_INSERT_AFTER(command
, *l
, end
, e
);
1969 int exec_command_set(ExecCommand
*c
, const char *path
, ...) {
1977 l
= strv_new_ap(path
, ap
);
1989 free_and_replace(c
->path
, p
);
1991 return strv_free_and_replace(c
->argv
, l
);
1994 int exec_command_append(ExecCommand
*c
, const char *path
, ...) {
1995 _cleanup_strv_free_
char **l
= NULL
;
2003 l
= strv_new_ap(path
, ap
);
2009 r
= strv_extend_strv(&c
->argv
, l
, false);
2016 static char *destroy_tree(char *path
) {
2020 if (!path_equal(path
, RUN_SYSTEMD_EMPTY
)) {
2021 log_debug("Spawning process to nuke '%s'", path
);
2023 (void) asynchronous_rm_rf(path
, REMOVE_ROOT
|REMOVE_SUBVOLUME
|REMOVE_PHYSICAL
);
2029 void exec_shared_runtime_done(ExecSharedRuntime
*rt
) {
2033 (void) hashmap_remove(rt
->manager
->exec_shared_runtime_by_id
, rt
->id
);
2035 rt
->id
= mfree(rt
->id
);
2036 rt
->tmp_dir
= mfree(rt
->tmp_dir
);
2037 rt
->var_tmp_dir
= mfree(rt
->var_tmp_dir
);
2038 safe_close_pair(rt
->netns_storage_socket
);
2039 safe_close_pair(rt
->ipcns_storage_socket
);
2042 static ExecSharedRuntime
* exec_shared_runtime_free(ExecSharedRuntime
*rt
) {
2046 exec_shared_runtime_done(rt
);
2050 DEFINE_TRIVIAL_UNREF_FUNC(ExecSharedRuntime
, exec_shared_runtime
, exec_shared_runtime_free
);
2051 DEFINE_TRIVIAL_CLEANUP_FUNC(ExecSharedRuntime
*, exec_shared_runtime_free
);
2053 ExecSharedRuntime
* exec_shared_runtime_destroy(ExecSharedRuntime
*rt
) {
2057 assert(rt
->n_ref
> 0);
2063 rt
->tmp_dir
= destroy_tree(rt
->tmp_dir
);
2064 rt
->var_tmp_dir
= destroy_tree(rt
->var_tmp_dir
);
2066 return exec_shared_runtime_free(rt
);
2069 static int exec_shared_runtime_allocate(ExecSharedRuntime
**ret
, const char *id
) {
2070 _cleanup_free_
char *id_copy
= NULL
;
2071 ExecSharedRuntime
*n
;
2075 id_copy
= strdup(id
);
2079 n
= new(ExecSharedRuntime
, 1);
2083 *n
= (ExecSharedRuntime
) {
2084 .id
= TAKE_PTR(id_copy
),
2085 .netns_storage_socket
= EBADF_PAIR
,
2086 .ipcns_storage_socket
= EBADF_PAIR
,
2093 static int exec_shared_runtime_add(
2098 int netns_storage_socket
[2],
2099 int ipcns_storage_socket
[2],
2100 ExecSharedRuntime
**ret
) {
2102 _cleanup_(exec_shared_runtime_freep
) ExecSharedRuntime
*rt
= NULL
;
2108 /* tmp_dir, var_tmp_dir, {net,ipc}ns_storage_socket fds are donated on success */
2110 r
= exec_shared_runtime_allocate(&rt
, id
);
2114 r
= hashmap_ensure_put(&m
->exec_shared_runtime_by_id
, &string_hash_ops
, rt
->id
, rt
);
2118 assert(!!rt
->tmp_dir
== !!rt
->var_tmp_dir
); /* We require both to be set together */
2119 rt
->tmp_dir
= TAKE_PTR(*tmp_dir
);
2120 rt
->var_tmp_dir
= TAKE_PTR(*var_tmp_dir
);
2122 if (netns_storage_socket
) {
2123 rt
->netns_storage_socket
[0] = TAKE_FD(netns_storage_socket
[0]);
2124 rt
->netns_storage_socket
[1] = TAKE_FD(netns_storage_socket
[1]);
2127 if (ipcns_storage_socket
) {
2128 rt
->ipcns_storage_socket
[0] = TAKE_FD(ipcns_storage_socket
[0]);
2129 rt
->ipcns_storage_socket
[1] = TAKE_FD(ipcns_storage_socket
[1]);
2136 /* do not remove created ExecSharedRuntime object when the operation succeeds. */
2141 static int exec_shared_runtime_make(
2143 const ExecContext
*c
,
2145 ExecSharedRuntime
**ret
) {
2147 _cleanup_(namespace_cleanup_tmpdirp
) char *tmp_dir
= NULL
, *var_tmp_dir
= NULL
;
2148 _cleanup_close_pair_
int netns_storage_socket
[2] = EBADF_PAIR
, ipcns_storage_socket
[2] = EBADF_PAIR
;
2155 /* It is not necessary to create ExecSharedRuntime object. */
2156 if (!exec_needs_network_namespace(c
) && !exec_needs_ipc_namespace(c
) && !c
->private_tmp
) {
2161 if (c
->private_tmp
&&
2162 !(prefixed_path_strv_contains(c
->inaccessible_paths
, "/tmp") &&
2163 (prefixed_path_strv_contains(c
->inaccessible_paths
, "/var/tmp") ||
2164 prefixed_path_strv_contains(c
->inaccessible_paths
, "/var")))) {
2165 r
= setup_tmp_dirs(id
, &tmp_dir
, &var_tmp_dir
);
2170 if (exec_needs_network_namespace(c
))
2171 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, netns_storage_socket
) < 0)
2174 if (exec_needs_ipc_namespace(c
))
2175 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, ipcns_storage_socket
) < 0)
2178 r
= exec_shared_runtime_add(m
, id
, &tmp_dir
, &var_tmp_dir
, netns_storage_socket
, ipcns_storage_socket
, ret
);
2185 int exec_shared_runtime_acquire(Manager
*m
, const ExecContext
*c
, const char *id
, bool create
, ExecSharedRuntime
**ret
) {
2186 ExecSharedRuntime
*rt
;
2193 rt
= hashmap_get(m
->exec_shared_runtime_by_id
, id
);
2195 /* We already have an ExecSharedRuntime object, let's increase the ref count and reuse it */
2203 /* If not found, then create a new object. */
2204 r
= exec_shared_runtime_make(m
, c
, id
, &rt
);
2208 /* When r == 0, it is not necessary to create ExecSharedRuntime object. */
2214 /* increment reference counter. */
2220 int exec_shared_runtime_serialize(const Manager
*m
, FILE *f
, FDSet
*fds
) {
2221 ExecSharedRuntime
*rt
;
2227 HASHMAP_FOREACH(rt
, m
->exec_shared_runtime_by_id
) {
2228 fprintf(f
, "exec-runtime=%s", rt
->id
);
2231 fprintf(f
, " tmp-dir=%s", rt
->tmp_dir
);
2233 if (rt
->var_tmp_dir
)
2234 fprintf(f
, " var-tmp-dir=%s", rt
->var_tmp_dir
);
2236 if (rt
->netns_storage_socket
[0] >= 0) {
2239 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[0]);
2243 fprintf(f
, " netns-socket-0=%i", copy
);
2246 if (rt
->netns_storage_socket
[1] >= 0) {
2249 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[1]);
2253 fprintf(f
, " netns-socket-1=%i", copy
);
2256 if (rt
->ipcns_storage_socket
[0] >= 0) {
2259 copy
= fdset_put_dup(fds
, rt
->ipcns_storage_socket
[0]);
2263 fprintf(f
, " ipcns-socket-0=%i", copy
);
2266 if (rt
->ipcns_storage_socket
[1] >= 0) {
2269 copy
= fdset_put_dup(fds
, rt
->ipcns_storage_socket
[1]);
2273 fprintf(f
, " ipcns-socket-1=%i", copy
);
2282 int exec_shared_runtime_deserialize_compat(Unit
*u
, const char *key
, const char *value
, FDSet
*fds
) {
2283 _cleanup_(exec_shared_runtime_freep
) ExecSharedRuntime
*rt_create
= NULL
;
2284 ExecSharedRuntime
*rt
= NULL
;
2287 /* This is for the migration from old (v237 or earlier) deserialization text.
2288 * Due to the bug #7790, this may not work with the units that use JoinsNamespaceOf=.
2289 * Even if the ExecSharedRuntime object originally created by the other unit, we cannot judge
2290 * so or not from the serialized text, then we always creates a new object owned by this. */
2296 /* Manager manages ExecSharedRuntime objects by the unit id.
2297 * So, we omit the serialized text when the unit does not have id (yet?)... */
2298 if (isempty(u
->id
)) {
2299 log_unit_debug(u
, "Invocation ID not found. Dropping runtime parameter.");
2304 if (hashmap_ensure_allocated(&u
->manager
->exec_shared_runtime_by_id
, &string_hash_ops
) < 0)
2307 rt
= hashmap_get(u
->manager
->exec_shared_runtime_by_id
, u
->id
);
2310 if (exec_shared_runtime_allocate(&rt_create
, u
->id
) < 0)
2316 if (streq(key
, "tmp-dir")) {
2317 if (free_and_strdup_warn(&rt
->tmp_dir
, value
) < 0)
2320 } else if (streq(key
, "var-tmp-dir")) {
2321 if (free_and_strdup_warn(&rt
->var_tmp_dir
, value
) < 0)
2324 } else if (streq(key
, "netns-socket-0")) {
2326 safe_close(rt
->netns_storage_socket
[0]);
2327 rt
->netns_storage_socket
[0] = deserialize_fd(fds
, value
);
2328 if (rt
->netns_storage_socket
[0] < 0)
2331 } else if (streq(key
, "netns-socket-1")) {
2333 safe_close(rt
->netns_storage_socket
[1]);
2334 rt
->netns_storage_socket
[1] = deserialize_fd(fds
, value
);
2335 if (rt
->netns_storage_socket
[1] < 0)
2340 /* If the object is newly created, then put it to the hashmap which manages ExecSharedRuntime objects. */
2341 if (rt_create
&& u
->manager
) {
2342 r
= hashmap_put(u
->manager
->exec_shared_runtime_by_id
, rt_create
->id
, rt_create
);
2344 log_unit_debug_errno(u
, r
, "Failed to put runtime parameter to manager's storage: %m");
2348 rt_create
->manager
= u
->manager
;
2351 TAKE_PTR(rt_create
);
2357 int exec_shared_runtime_deserialize_one(Manager
*m
, const char *value
, FDSet
*fds
) {
2358 _cleanup_free_
char *tmp_dir
= NULL
, *var_tmp_dir
= NULL
;
2360 int r
, netns_fdpair
[] = {-1, -1}, ipcns_fdpair
[] = {-1, -1};
2361 const char *p
, *v
= ASSERT_PTR(value
);
2367 n
= strcspn(v
, " ");
2368 id
= strndupa_safe(v
, n
);
2373 v
= startswith(p
, "tmp-dir=");
2375 n
= strcspn(v
, " ");
2376 tmp_dir
= strndup(v
, n
);
2384 v
= startswith(p
, "var-tmp-dir=");
2386 n
= strcspn(v
, " ");
2387 var_tmp_dir
= strndup(v
, n
);
2395 v
= startswith(p
, "netns-socket-0=");
2399 n
= strcspn(v
, " ");
2400 buf
= strndupa_safe(v
, n
);
2402 netns_fdpair
[0] = deserialize_fd(fds
, buf
);
2403 if (netns_fdpair
[0] < 0)
2404 return netns_fdpair
[0];
2410 v
= startswith(p
, "netns-socket-1=");
2414 n
= strcspn(v
, " ");
2415 buf
= strndupa_safe(v
, n
);
2417 netns_fdpair
[1] = deserialize_fd(fds
, buf
);
2418 if (netns_fdpair
[1] < 0)
2419 return netns_fdpair
[1];
2425 v
= startswith(p
, "ipcns-socket-0=");
2429 n
= strcspn(v
, " ");
2430 buf
= strndupa_safe(v
, n
);
2432 ipcns_fdpair
[0] = deserialize_fd(fds
, buf
);
2433 if (ipcns_fdpair
[0] < 0)
2434 return ipcns_fdpair
[0];
2440 v
= startswith(p
, "ipcns-socket-1=");
2444 n
= strcspn(v
, " ");
2445 buf
= strndupa_safe(v
, n
);
2447 ipcns_fdpair
[1] = deserialize_fd(fds
, buf
);
2448 if (ipcns_fdpair
[1] < 0)
2449 return ipcns_fdpair
[1];
2453 r
= exec_shared_runtime_add(m
, id
, &tmp_dir
, &var_tmp_dir
, netns_fdpair
, ipcns_fdpair
, NULL
);
2455 return log_debug_errno(r
, "Failed to add exec-runtime: %m");
2459 void exec_shared_runtime_vacuum(Manager
*m
) {
2460 ExecSharedRuntime
*rt
;
2464 /* Free unreferenced ExecSharedRuntime objects. This is used after manager deserialization process. */
2466 HASHMAP_FOREACH(rt
, m
->exec_shared_runtime_by_id
) {
2470 (void) exec_shared_runtime_free(rt
);
2474 int exec_runtime_make(
2476 const ExecContext
*context
,
2477 ExecSharedRuntime
*shared
,
2478 DynamicCreds
*creds
,
2479 ExecRuntime
**ret
) {
2480 _cleanup_close_pair_
int ephemeral_storage_socket
[2] = EBADF_PAIR
;
2481 _cleanup_free_
char *ephemeral
= NULL
;
2482 _cleanup_(exec_runtime_freep
) ExecRuntime
*rt
= NULL
;
2489 if (!shared
&& !creds
&& !exec_needs_ephemeral(context
)) {
2494 if (exec_needs_ephemeral(context
)) {
2495 r
= mkdir_p("/var/lib/systemd/ephemeral-trees", 0755);
2499 r
= tempfn_random_child("/var/lib/systemd/ephemeral-trees", unit
->id
, &ephemeral
);
2503 if (socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, ephemeral_storage_socket
) < 0)
2507 rt
= new(ExecRuntime
, 1);
2511 *rt
= (ExecRuntime
) {
2513 .dynamic_creds
= creds
,
2514 .ephemeral_copy
= TAKE_PTR(ephemeral
),
2515 .ephemeral_storage_socket
[0] = TAKE_FD(ephemeral_storage_socket
[0]),
2516 .ephemeral_storage_socket
[1] = TAKE_FD(ephemeral_storage_socket
[1]),
2519 *ret
= TAKE_PTR(rt
);
2523 ExecRuntime
* exec_runtime_free(ExecRuntime
*rt
) {
2527 exec_shared_runtime_unref(rt
->shared
);
2528 dynamic_creds_unref(rt
->dynamic_creds
);
2530 rt
->ephemeral_copy
= destroy_tree(rt
->ephemeral_copy
);
2532 safe_close_pair(rt
->ephemeral_storage_socket
);
2536 ExecRuntime
* exec_runtime_destroy(ExecRuntime
*rt
) {
2540 rt
->shared
= exec_shared_runtime_destroy(rt
->shared
);
2541 rt
->dynamic_creds
= dynamic_creds_destroy(rt
->dynamic_creds
);
2542 return exec_runtime_free(rt
);
2545 void exec_runtime_clear(ExecRuntime
*rt
) {
2549 safe_close_pair(rt
->ephemeral_storage_socket
);
2550 rt
->ephemeral_copy
= mfree(rt
->ephemeral_copy
);
2553 void exec_params_shallow_clear(ExecParameters
*p
) {
2557 /* This is called on the PID1 side, as many of the struct's FDs are only borrowed, and actually
2558 * owned by the manager or other objects, and reused across multiple units. */
2560 p
->environment
= strv_free(p
->environment
);
2561 p
->fd_names
= strv_free(p
->fd_names
);
2562 p
->files_env
= strv_free(p
->files_env
);
2563 p
->fds
= mfree(p
->fds
);
2564 p
->exec_fd
= safe_close(p
->exec_fd
);
2565 p
->user_lookup_fd
= -EBADF
;
2566 p
->bpf_restrict_fs_map_fd
= -EBADF
;
2567 p
->unit_id
= mfree(p
->unit_id
);
2568 p
->invocation_id
= SD_ID128_NULL
;
2569 p
->invocation_id_string
[0] = '\0';
2570 p
->confirm_spawn
= mfree(p
->confirm_spawn
);
2573 void exec_params_deep_clear(ExecParameters
*p
) {
2577 /* This is called on the sd-executor side, where everything received is owned by the process and has
2578 * to be fully cleaned up to make sanitizers and analyzers happy, as opposed as the shallow clean
2579 * function above. */
2581 close_many_unset(p
->fds
, p
->n_socket_fds
+ p
->n_storage_fds
);
2583 p
->cgroup_path
= mfree(p
->cgroup_path
);
2586 free_many_charp(p
->prefix
, _EXEC_DIRECTORY_TYPE_MAX
);
2587 p
->prefix
= mfree(p
->prefix
);
2590 p
->received_credentials_directory
= mfree(p
->received_credentials_directory
);
2591 p
->received_encrypted_credentials_directory
= mfree(p
->received_encrypted_credentials_directory
);
2594 close_many_and_free(p
->idle_pipe
, 4);
2595 p
->idle_pipe
= NULL
;
2598 p
->stdin_fd
= safe_close(p
->stdin_fd
);
2599 p
->stdout_fd
= safe_close(p
->stdout_fd
);
2600 p
->stderr_fd
= safe_close(p
->stderr_fd
);
2602 p
->notify_socket
= mfree(p
->notify_socket
);
2604 open_file_free_many(&p
->open_files
);
2606 p
->fallback_smack_process_label
= mfree(p
->fallback_smack_process_label
);
2608 exec_params_shallow_clear(p
);
2611 void exec_directory_done(ExecDirectory
*d
) {
2615 FOREACH_ARRAY(i
, d
->items
, d
->n_items
) {
2617 strv_free(i
->symlinks
);
2620 d
->items
= mfree(d
->items
);
2625 static ExecDirectoryItem
*exec_directory_find(ExecDirectory
*d
, const char *path
) {
2629 FOREACH_ARRAY(i
, d
->items
, d
->n_items
)
2630 if (path_equal(i
->path
, path
))
2636 int exec_directory_add(ExecDirectory
*d
, const char *path
, const char *symlink
) {
2637 _cleanup_strv_free_
char **s
= NULL
;
2638 _cleanup_free_
char *p
= NULL
;
2639 ExecDirectoryItem
*existing
;
2645 existing
= exec_directory_find(d
, path
);
2647 r
= strv_extend(&existing
->symlinks
, symlink
);
2651 return 0; /* existing item is updated */
2659 s
= strv_new(symlink
);
2664 if (!GREEDY_REALLOC(d
->items
, d
->n_items
+ 1))
2667 d
->items
[d
->n_items
++] = (ExecDirectoryItem
) {
2668 .path
= TAKE_PTR(p
),
2669 .symlinks
= TAKE_PTR(s
),
2672 return 1; /* new item is added */
2675 static int exec_directory_item_compare_func(const ExecDirectoryItem
*a
, const ExecDirectoryItem
*b
) {
2679 return path_compare(a
->path
, b
->path
);
2682 void exec_directory_sort(ExecDirectory
*d
) {
2685 /* Sort the exec directories to make always parent directories processed at first in
2686 * setup_exec_directory(), e.g., even if StateDirectory=foo/bar foo, we need to create foo at first,
2687 * then foo/bar. Also, set .only_create flag if one of the parent directories is contained in the
2688 * list. See also comments in setup_exec_directory() and issue #24783. */
2690 if (d
->n_items
<= 1)
2693 typesafe_qsort(d
->items
, d
->n_items
, exec_directory_item_compare_func
);
2695 for (size_t i
= 1; i
< d
->n_items
; i
++)
2696 for (size_t j
= 0; j
< i
; j
++)
2697 if (path_startswith(d
->items
[i
].path
, d
->items
[j
].path
)) {
2698 d
->items
[i
].only_create
= true;
2703 ExecCleanMask
exec_clean_mask_from_string(const char *s
) {
2704 ExecDirectoryType t
;
2708 if (streq(s
, "all"))
2709 return EXEC_CLEAN_ALL
;
2710 if (streq(s
, "fdstore"))
2711 return EXEC_CLEAN_FDSTORE
;
2713 t
= exec_resource_type_from_string(s
);
2715 return (ExecCleanMask
) t
;
2720 static const char* const exec_input_table
[_EXEC_INPUT_MAX
] = {
2721 [EXEC_INPUT_NULL
] = "null",
2722 [EXEC_INPUT_TTY
] = "tty",
2723 [EXEC_INPUT_TTY_FORCE
] = "tty-force",
2724 [EXEC_INPUT_TTY_FAIL
] = "tty-fail",
2725 [EXEC_INPUT_SOCKET
] = "socket",
2726 [EXEC_INPUT_NAMED_FD
] = "fd",
2727 [EXEC_INPUT_DATA
] = "data",
2728 [EXEC_INPUT_FILE
] = "file",
2731 DEFINE_STRING_TABLE_LOOKUP(exec_input
, ExecInput
);
2733 static const char* const exec_output_table
[_EXEC_OUTPUT_MAX
] = {
2734 [EXEC_OUTPUT_INHERIT
] = "inherit",
2735 [EXEC_OUTPUT_NULL
] = "null",
2736 [EXEC_OUTPUT_TTY
] = "tty",
2737 [EXEC_OUTPUT_KMSG
] = "kmsg",
2738 [EXEC_OUTPUT_KMSG_AND_CONSOLE
] = "kmsg+console",
2739 [EXEC_OUTPUT_JOURNAL
] = "journal",
2740 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE
] = "journal+console",
2741 [EXEC_OUTPUT_SOCKET
] = "socket",
2742 [EXEC_OUTPUT_NAMED_FD
] = "fd",
2743 [EXEC_OUTPUT_FILE
] = "file",
2744 [EXEC_OUTPUT_FILE_APPEND
] = "append",
2745 [EXEC_OUTPUT_FILE_TRUNCATE
] = "truncate",
2748 DEFINE_STRING_TABLE_LOOKUP(exec_output
, ExecOutput
);
2750 static const char* const exec_utmp_mode_table
[_EXEC_UTMP_MODE_MAX
] = {
2751 [EXEC_UTMP_INIT
] = "init",
2752 [EXEC_UTMP_LOGIN
] = "login",
2753 [EXEC_UTMP_USER
] = "user",
2756 DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode
, ExecUtmpMode
);
2758 static const char* const exec_preserve_mode_table
[_EXEC_PRESERVE_MODE_MAX
] = {
2759 [EXEC_PRESERVE_NO
] = "no",
2760 [EXEC_PRESERVE_YES
] = "yes",
2761 [EXEC_PRESERVE_RESTART
] = "restart",
2764 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode
, ExecPreserveMode
, EXEC_PRESERVE_YES
);
2766 /* This table maps ExecDirectoryType to the setting it is configured with in the unit */
2767 static const char* const exec_directory_type_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2768 [EXEC_DIRECTORY_RUNTIME
] = "RuntimeDirectory",
2769 [EXEC_DIRECTORY_STATE
] = "StateDirectory",
2770 [EXEC_DIRECTORY_CACHE
] = "CacheDirectory",
2771 [EXEC_DIRECTORY_LOGS
] = "LogsDirectory",
2772 [EXEC_DIRECTORY_CONFIGURATION
] = "ConfigurationDirectory",
2775 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type
, ExecDirectoryType
);
2777 /* This table maps ExecDirectoryType to the symlink setting it is configured with in the unit */
2778 static const char* const exec_directory_type_symlink_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2779 [EXEC_DIRECTORY_RUNTIME
] = "RuntimeDirectorySymlink",
2780 [EXEC_DIRECTORY_STATE
] = "StateDirectorySymlink",
2781 [EXEC_DIRECTORY_CACHE
] = "CacheDirectorySymlink",
2782 [EXEC_DIRECTORY_LOGS
] = "LogsDirectorySymlink",
2783 [EXEC_DIRECTORY_CONFIGURATION
] = "ConfigurationDirectorySymlink",
2786 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type_symlink
, ExecDirectoryType
);
2788 static const char* const exec_directory_type_mode_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2789 [EXEC_DIRECTORY_RUNTIME
] = "RuntimeDirectoryMode",
2790 [EXEC_DIRECTORY_STATE
] = "StateDirectoryMode",
2791 [EXEC_DIRECTORY_CACHE
] = "CacheDirectoryMode",
2792 [EXEC_DIRECTORY_LOGS
] = "LogsDirectoryMode",
2793 [EXEC_DIRECTORY_CONFIGURATION
] = "ConfigurationDirectoryMode",
2796 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type_mode
, ExecDirectoryType
);
2798 /* And this table maps ExecDirectoryType too, but to a generic term identifying the type of resource. This
2799 * one is supposed to be generic enough to be used for unit types that don't use ExecContext and per-unit
2800 * directories, specifically .timer units with their timestamp touch file. */
2801 static const char* const exec_resource_type_table
[_EXEC_DIRECTORY_TYPE_MAX
] = {
2802 [EXEC_DIRECTORY_RUNTIME
] = "runtime",
2803 [EXEC_DIRECTORY_STATE
] = "state",
2804 [EXEC_DIRECTORY_CACHE
] = "cache",
2805 [EXEC_DIRECTORY_LOGS
] = "logs",
2806 [EXEC_DIRECTORY_CONFIGURATION
] = "configuration",
2809 DEFINE_STRING_TABLE_LOOKUP(exec_resource_type
, ExecDirectoryType
);
2811 static const char* const exec_keyring_mode_table
[_EXEC_KEYRING_MODE_MAX
] = {
2812 [EXEC_KEYRING_INHERIT
] = "inherit",
2813 [EXEC_KEYRING_PRIVATE
] = "private",
2814 [EXEC_KEYRING_SHARED
] = "shared",
2817 DEFINE_STRING_TABLE_LOOKUP(exec_keyring_mode
, ExecKeyringMode
);