From: Luca Boccassi Date: Thu, 31 Aug 2023 20:08:49 +0000 (+0100) Subject: core: ensure execute/spawn functions can work without manager object X-Git-Tag: v255-rc1~250^2~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=154eb43f384be360a42db3c9190ee15ca38c51ba;p=thirdparty%2Fsystemd.git core: ensure execute/spawn functions can work without manager object When switching to serialization later, the Manager object will not be serialized, move parameters around instead --- diff --git a/src/core/bpf-lsm.c b/src/core/bpf-lsm.c index 22200bd9393..300486597b3 100644 --- a/src/core/bpf-lsm.c +++ b/src/core/bpf-lsm.c @@ -154,7 +154,8 @@ int lsm_bpf_setup(Manager *m) { return 0; } -int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allow_list) { +int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, int outer_map_fd, bool allow_list) { + _cleanup_close_ int outer_map_fd_cleanup = -EBADF; uint32_t dummy_value = 1, zero = 0; const char *fs; const statfs_f_type_t *magic; @@ -162,8 +163,9 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo assert(filesystems); assert(u); + assert(outer_map_fd >= 0 || u->manager); - if (!u->manager->restrict_fs) + if (u->manager && !u->manager->restrict_fs) /* Might be called in sd-executor with no manager object */ return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL), "bpf-lsm: BPF LSM object is not installed, has setup failed?"); @@ -177,9 +179,11 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo if (inner_map_fd < 0) return log_unit_error_errno(u, errno, "bpf-lsm: Failed to create inner BPF map: %m"); - int outer_map_fd = sym_bpf_map__fd(u->manager->restrict_fs->maps.cgroup_hash); - if (outer_map_fd < 0) - return log_unit_error_errno(u, errno, "bpf-lsm: Failed to get BPF map fd: %m"); + if (outer_map_fd < 0) { + outer_map_fd_cleanup = outer_map_fd = sym_bpf_map__fd(u->manager->restrict_fs->maps.cgroup_hash); + if (outer_map_fd < 0) + return log_unit_error_errno(u, errno, "bpf-lsm: Failed to get BPF map fd: %m"); + } if (sym_bpf_map_update_elem(outer_map_fd, &u->cgroup_id, &inner_map_fd, BPF_ANY) != 0) return log_unit_error_errno(u, errno, "bpf-lsm: Error populating BPF map: %m"); @@ -263,7 +267,7 @@ int lsm_bpf_setup(Manager *m) { return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to set up LSM BPF: %m"); } -int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, const bool allow_list) { +int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, int outer_map_fd, const bool allow_list) { return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to restrict filesystems using LSM BPF: %m"); } diff --git a/src/core/bpf-lsm.h b/src/core/bpf-lsm.h index dff581279d7..5eb03ae7fb4 100644 --- a/src/core/bpf-lsm.h +++ b/src/core/bpf-lsm.h @@ -16,7 +16,7 @@ typedef struct restrict_fs_bpf restrict_fs_bpf; bool lsm_bpf_supported(bool initialize); int lsm_bpf_setup(Manager *m); -int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allow_list); +int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, int outer_map_fd, bool allow_list); int lsm_bpf_cleanup(const Unit *u); int lsm_bpf_map_restrict_fs_fd(Unit *u); void lsm_bpf_destroy(struct restrict_fs_bpf *prog); diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 47bab04f421..69c9d9a9bbe 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -143,7 +143,14 @@ static void cgroup_compat_warn(void) { void cgroup_context_init(CGroupContext *c) { assert(c); - /* Initialize everything to the kernel defaults. */ + /* Initialize everything to the kernel defaults. When initializing a bool member to 'true', make + * sure to serialize in execute-serialize.c using serialize_bool() instead of + * serialize_bool_elide(), as sd-executor will initialize here to 'true', but serialize_bool_elide() + * skips serialization if the value is 'false' (as that's the common default), so if the value at + * runtime is zero it would be lost after deserialization. Same when initializing uint64_t and other + * values, update/add a conditional serialization check. This is to minimize the amount of + * serialized data that is sent to the sd-executor, so that there is less work to do on the default + * cases. */ *c = (CGroupContext) { .cpu_weight = CGROUP_WEIGHT_INVALID, diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index e99a6694f6f..2cab0d44acb 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -26,7 +26,7 @@ /* Takes a value generated randomly or by hashing and turns it into a UID in the right range */ #define UID_CLAMP_INTO_RANGE(rnd) (((uid_t) (rnd) % (DYNAMIC_UID_MAX - DYNAMIC_UID_MIN + 1)) + DYNAMIC_UID_MIN) -DEFINE_PRIVATE_TRIVIAL_REF_FUNC(DynamicUser, dynamic_user); +DEFINE_TRIVIAL_REF_FUNC(DynamicUser, dynamic_user); static DynamicUser* dynamic_user_free(DynamicUser *d) { if (!d) @@ -43,13 +43,15 @@ static int dynamic_user_add(Manager *m, const char *name, int storage_socket[sta DynamicUser *d; int r; - assert(m); + assert(m || ret); assert(name); assert(storage_socket); - r = hashmap_ensure_allocated(&m->dynamic_users, &string_hash_ops); - if (r < 0) - return r; + if (m) { /* Might be called in sd-executor with no manager object */ + r = hashmap_ensure_allocated(&m->dynamic_users, &string_hash_ops); + if (r < 0) + return r; + } d = malloc0(offsetof(DynamicUser, name) + strlen(name) + 1); if (!d) @@ -60,10 +62,12 @@ static int dynamic_user_add(Manager *m, const char *name, int storage_socket[sta d->storage_socket[0] = storage_socket[0]; d->storage_socket[1] = storage_socket[1]; - r = hashmap_put(m->dynamic_users, d->name, d); - if (r < 0) { - free(d); - return r; + if (m) { /* Might be called in sd-executor with no manager object */ + r = hashmap_put(m->dynamic_users, d->name, d); + if (r < 0) { + free(d); + return r; + } } d->manager = m; @@ -603,37 +607,49 @@ static DynamicUser* dynamic_user_destroy(DynamicUser *d) { return dynamic_user_free(d); } -int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds) { - DynamicUser *d; +int dynamic_user_serialize_one(DynamicUser *d, const char *key, FILE *f, FDSet *fds) { + int copy0, copy1; - assert(m); + assert(key); assert(f); assert(fds); - /* Dump the dynamic user database into the manager serialization, to deal with daemon reloads. */ + if (!d) + return 0; - HASHMAP_FOREACH(d, m->dynamic_users) { - int copy0, copy1; + if (d->storage_socket[0] < 0 || d->storage_socket[1] < 0) + return 0; - copy0 = fdset_put_dup(fds, d->storage_socket[0]); - if (copy0 < 0) - return log_error_errno(copy0, "Failed to add dynamic user storage fd to serialization: %m"); + copy0 = fdset_put_dup(fds, d->storage_socket[0]); + if (copy0 < 0) + return log_error_errno(copy0, "Failed to add dynamic user storage fd to serialization: %m"); - copy1 = fdset_put_dup(fds, d->storage_socket[1]); - if (copy1 < 0) - return log_error_errno(copy1, "Failed to add dynamic user storage fd to serialization: %m"); + copy1 = fdset_put_dup(fds, d->storage_socket[1]); + if (copy1 < 0) + return log_error_errno(copy1, "Failed to add dynamic user storage fd to serialization: %m"); - (void) serialize_item_format(f, "dynamic-user", "%s %i %i", d->name, copy0, copy1); - } + (void) serialize_item_format(f, key, "%s %i %i", d->name, copy0, copy1); + + return 0; +} + +int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds) { + DynamicUser *d; + + assert(m); + + /* Dump the dynamic user database into the manager serialization, to deal with daemon reloads. */ + + HASHMAP_FOREACH(d, m->dynamic_users) + (void) dynamic_user_serialize_one(d, "dynamic-user", f, fds); return 0; } -void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds) { +void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds, DynamicUser **ret) { _cleanup_free_ char *name = NULL, *s0 = NULL, *s1 = NULL; int r, fd0, fd1; - assert(m); assert(value); assert(fds); @@ -655,7 +671,7 @@ void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds) { return; } - r = dynamic_user_add(m, name, (int[]) { fd0, fd1 }, NULL); + r = dynamic_user_add(m, name, (int[]) { fd0, fd1 }, ret); if (r < 0) { log_debug_errno(r, "Failed to add dynamic user: %m"); return; @@ -663,6 +679,9 @@ void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds) { (void) fdset_remove(fds, fd0); (void) fdset_remove(fds, fd1); + + if (ret) /* If the caller uses it directly, increment the refcount */ + (*ret)->n_ref++; } void dynamic_user_vacuum(Manager *m, bool close_user) { diff --git a/src/core/dynamic-user.h b/src/core/dynamic-user.h index 6539d17571b..679c588a76d 100644 --- a/src/core/dynamic-user.h +++ b/src/core/dynamic-user.h @@ -26,7 +26,8 @@ struct DynamicUser { }; int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds); -void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds); +int dynamic_user_serialize_one(DynamicUser *d, const char *key, FILE *f, FDSet *fds); +void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds, DynamicUser **ret); void dynamic_user_vacuum(Manager *m, bool close_user); int dynamic_user_current(DynamicUser *d, uid_t *ret); @@ -41,3 +42,5 @@ DynamicCreds *dynamic_creds_destroy(DynamicCreds *creds); DEFINE_TRIVIAL_CLEANUP_FUNC(DynamicCreds*, dynamic_creds_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(DynamicCreds*, dynamic_creds_destroy); + +DynamicUser *dynamic_user_ref(DynamicUser *user); diff --git a/src/core/execute.c b/src/core/execute.c index a45da470bd0..e305e7b8be6 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -58,6 +58,7 @@ #include "execute.h" #include "exit-status.h" #include "fd-util.h" +#include "fileio.h" #include "format-util.h" #include "glob-util.h" #include "hexdecoct.h" @@ -1770,20 +1771,21 @@ static int apply_lock_personality(const Unit* u, const ExecContext *c) { #endif #if HAVE_LIBBPF -static int apply_restrict_filesystems(Unit *u, const ExecContext *c) { +static int apply_restrict_filesystems(Unit *u, const ExecContext *c, const ExecParameters *p) { assert(u); assert(c); + assert(p); if (!exec_context_restrict_filesystems_set(c)) return 0; - if (!u->manager->restrict_fs) { + if (p->bpf_outer_map_fd < 0) { /* LSM BPF is unsupported or lsm_bpf_setup failed */ log_unit_debug(u, "LSM BPF not supported, skipping RestrictFileSystems="); return 0; } - return lsm_bpf_unit_restrict_filesystems(u, c->restrict_filesystems, c->restrict_filesystems_allow_list); + return lsm_bpf_unit_restrict_filesystems(u, c->restrict_filesystems, p->bpf_outer_map_fd, c->restrict_filesystems_allow_list); } #endif @@ -2738,26 +2740,26 @@ fail: #if ENABLE_SMACK static int setup_smack( - const Manager *manager, + const ExecParameters *params, const ExecContext *context, int executable_fd) { int r; - assert(context); + assert(params); assert(executable_fd >= 0); if (context->smack_process_label) { r = mac_smack_apply_pid(0, context->smack_process_label); if (r < 0) return r; - } else if (manager->defaults.smack_process_label) { + } else if (params->fallback_smack_process_label) { _cleanup_free_ char *exec_label = NULL; r = mac_smack_read_fd(executable_fd, SMACK_ATTR_EXEC, &exec_label); if (r < 0 && !ERRNO_IS_XATTR_ABSENT(r)) return r; - r = mac_smack_apply_pid(0, exec_label ?: manager->defaults.smack_process_label); + r = mac_smack_apply_pid(0, exec_label ?: params->fallback_smack_process_label); if (r < 0) return r; } @@ -3540,7 +3542,6 @@ static void append_socket_pair(int *array, size_t *n, const int pair[static 2]) static int close_remaining_fds( const ExecParameters *params, const ExecRuntime *runtime, - int user_lookup_fd, int socket_fd, const int *fds, size_t n_fds) { @@ -3578,8 +3579,8 @@ static int close_remaining_fds( append_socket_pair(dont_close, &n_dont_close, runtime->dynamic_creds->group->storage_socket); } - if (user_lookup_fd >= 0) - dont_close[n_dont_close++] = user_lookup_fd; + if (params->user_lookup_fd >= 0) + dont_close[n_dont_close++] = params->user_lookup_fd; return close_all_fds(dont_close, n_dont_close); } @@ -3950,20 +3951,16 @@ static bool exec_context_need_unprivileged_private_users( !strv_isempty(context->no_exec_paths); } +static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***l); +static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[static 3]); + static int exec_child( Unit *unit, const ExecCommand *command, const ExecContext *context, - const ExecParameters *params, + ExecParameters *params, ExecRuntime *runtime, const CGroupContext *cgroup_context, - int socket_fd, - const int named_iofds[static 3], - int *params_fds, - size_t n_socket_fds, - size_t n_storage_fds, - char **files_env, - int user_lookup_fd, int *exit_status) { _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **joined_exec_search_path = NULL, **accum_env = NULL, **replaced_argv = NULL; @@ -3994,13 +3991,15 @@ static int exec_child( gid_t saved_gid = getgid(); uid_t uid = UID_INVALID; gid_t gid = GID_INVALID; - size_t n_fds = n_socket_fds + n_storage_fds, /* fds to pass to the child */ + size_t n_fds, /* fds to pass to the child */ n_keep_fds; /* total number of fds not to close */ int secure_bits; _cleanup_free_ gid_t *gids_after_pam = NULL; int ngids_after_pam = 0; _cleanup_free_ int *fds = NULL; _cleanup_strv_free_ char **fdnames = NULL; + int socket_fd = -EBADF, named_iofds[3] = { -EBADF, -EBADF, -EBADF }, *params_fds = NULL; + size_t n_storage_fds = 0, n_socket_fds = 0; assert(unit); assert(command); @@ -4012,6 +4011,28 @@ static int exec_child( assert(command->path); assert(!strv_isempty(command->argv)); + if (context->std_input == EXEC_INPUT_SOCKET || + context->std_output == EXEC_OUTPUT_SOCKET || + context->std_error == EXEC_OUTPUT_SOCKET) { + + if (params->n_socket_fds > 1) + return log_unit_error_errno(unit, SYNTHETIC_ERRNO(EINVAL), "Got more than one socket."); + + if (params->n_socket_fds == 0) + return log_unit_error_errno(unit, SYNTHETIC_ERRNO(EINVAL), "Got no socket."); + + socket_fd = params->fds[0]; + } else { + params_fds = params->fds; + n_socket_fds = params->n_socket_fds; + n_storage_fds = params->n_storage_fds; + } + n_fds = n_socket_fds + n_storage_fds; + + r = exec_context_named_iofds(context, params, named_iofds); + if (r < 0) + return log_unit_error_errno(unit, r, "Failed to load a named file descriptor: %m"); + rename_process_from_path(command->path); /* We reset exactly these signals, since they are the only ones we set to SIG_IGN in the main @@ -4075,14 +4096,8 @@ static int exec_child( } #if HAVE_LIBBPF - if (unit->manager->restrict_fs) { - int bpf_map_fd = lsm_bpf_map_restrict_fs_fd(unit); - if (bpf_map_fd < 0) { - *exit_status = EXIT_FDS; - return log_unit_error_errno(unit, bpf_map_fd, "Failed to get restrict filesystems BPF map fd: %m"); - } - - r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, bpf_map_fd, &bpf_map_fd); + if (params->bpf_outer_map_fd >= 0) { + r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, params->bpf_outer_map_fd, (int *)¶ms->bpf_outer_map_fd); if (r < 0) { *exit_status = EXIT_FDS; return log_unit_error_errno(unit, r, "Failed to shift fd and set FD_CLOEXEC: %m"); @@ -4090,7 +4105,7 @@ static int exec_child( } #endif - r = close_remaining_fds(params, runtime, user_lookup_fd, socket_fd, keep_fds, n_keep_fds); + r = close_remaining_fds(params, runtime, socket_fd, keep_fds, n_keep_fds); if (r < 0) { *exit_status = EXIT_FDS; return log_unit_error_errno(unit, r, "Failed to close unwanted file descriptors: %m"); @@ -4104,7 +4119,7 @@ static int exec_child( exec_context_tty_reset(context, params); - if (unit_shall_confirm_spawn(unit)) { + if (params->shall_confirm_spawn && unit_shall_confirm_spawn(unit)) { _cleanup_free_ char *cmdline = NULL; cmdline = quote_command_line(command->argv, SHELL_ESCAPE_EMPTY); @@ -4201,13 +4216,13 @@ static int exec_child( return log_unit_error_errno(unit, r, "Failed to determine supplementary groups: %m"); } - r = send_user_lookup(unit, user_lookup_fd, uid, gid); + r = send_user_lookup(unit, params->user_lookup_fd, uid, gid); if (r < 0) { *exit_status = EXIT_USER; return log_unit_error_errno(unit, r, "Failed to send user credentials to PID1: %m"); } - user_lookup_fd = safe_close(user_lookup_fd); + params->user_lookup_fd = safe_close(params->user_lookup_fd); r = acquire_home(context, uid, &home, &home_buffer); if (r < 0) { @@ -4513,7 +4528,7 @@ static int exec_child( joined_exec_search_path, pass_env, context->environment, - files_env); + params->files_env); if (!accum_env) { *exit_status = EXIT_MEMORY; return log_oom(); @@ -4830,7 +4845,7 @@ static int exec_child( /* LSM Smack needs the capability CAP_MAC_ADMIN to change the current execution security context of the * process. This is the latest place before dropping capabilities. Other MAC context are set later. */ if (use_smack) { - r = setup_smack(unit->manager, context, executable_fd); + r = setup_smack(params, context, executable_fd); if (r < 0 && !context->smack_process_label_ignore) { *exit_status = EXIT_SMACK_PROCESS_LABEL; return log_unit_error_errno(unit, r, "Failed to set SMACK process label: %m"); @@ -5060,7 +5075,7 @@ static int exec_child( #endif #if HAVE_LIBBPF - r = apply_restrict_filesystems(unit, context); + r = apply_restrict_filesystems(unit, context, params); if (r < 0) { *exit_status = EXIT_BPF; return log_unit_error_errno(unit, r, "Failed to restrict filesystems: %m"); @@ -5135,24 +5150,21 @@ static int exec_child( return log_unit_error_errno(unit, r, "Failed to execute %s: %m", executable); } -static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***l); -static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[static 3]); int exec_spawn(Unit *unit, ExecCommand *command, const ExecContext *context, - const ExecParameters *params, + ExecParameters *params, ExecRuntime *runtime, const CGroupContext *cgroup_context, pid_t *ret) { - int socket_fd, r, named_iofds[3] = { -1, -1, -1 }, *fds = NULL; _cleanup_free_ char *subcgroup_path = NULL; - _cleanup_strv_free_ char **files_env = NULL; - size_t n_storage_fds = 0, n_socket_fds = 0; pid_t pid; + int r; assert(unit); + assert(unit->manager); assert(command); assert(context); assert(ret); @@ -5161,29 +5173,7 @@ int exec_spawn(Unit *unit, LOG_CONTEXT_PUSH_UNIT(unit); - if (context->std_input == EXEC_INPUT_SOCKET || - context->std_output == EXEC_OUTPUT_SOCKET || - context->std_error == EXEC_OUTPUT_SOCKET) { - - if (params->n_socket_fds > 1) - return log_unit_error_errno(unit, SYNTHETIC_ERRNO(EINVAL), "Got more than one socket."); - - if (params->n_socket_fds == 0) - return log_unit_error_errno(unit, SYNTHETIC_ERRNO(EINVAL), "Got no socket."); - - socket_fd = params->fds[0]; - } else { - socket_fd = -EBADF; - fds = params->fds; - n_socket_fds = params->n_socket_fds; - n_storage_fds = params->n_storage_fds; - } - - r = exec_context_named_iofds(context, params, named_iofds); - if (r < 0) - return log_unit_error_errno(unit, r, "Failed to load a named file descriptor: %m"); - - r = exec_context_load_environment(unit, context, &files_env); + r = exec_context_load_environment(unit, context, ¶ms->files_env); if (r < 0) return log_unit_error_errno(unit, r, "Failed to load environment files: %m"); @@ -5222,13 +5212,6 @@ int exec_spawn(Unit *unit, params, runtime, cgroup_context, - socket_fd, - named_iofds, - fds, - n_socket_fds, - n_storage_fds, - files_env, - unit->manager->user_lookup_fds[1], &exit_status); if (r < 0) { @@ -5264,6 +5247,9 @@ int exec_spawn(Unit *unit, void exec_context_init(ExecContext *c) { assert(c); + /* When initializing a bool member to 'true', make sure to serialize in execute-serialize.c using + * serialize_bool() instead of serialize_bool_elide(). */ + *c = (ExecContext) { .umask = 0022, .ioprio = IOPRIO_DEFAULT_CLASS_AND_PRIO, @@ -6811,7 +6797,7 @@ int exec_shared_runtime_serialize(const Manager *m, FILE *f, FDSet *fds) { int exec_shared_runtime_deserialize_compat(Unit *u, const char *key, const char *value, FDSet *fds) { _cleanup_(exec_shared_runtime_freep) ExecSharedRuntime *rt_create = NULL; - ExecSharedRuntime *rt; + ExecSharedRuntime *rt = NULL; int r; /* This is for the migration from old (v237 or earlier) deserialization text. @@ -6830,10 +6816,12 @@ int exec_shared_runtime_deserialize_compat(Unit *u, const char *key, const char return 0; } - if (hashmap_ensure_allocated(&u->manager->exec_shared_runtime_by_id, &string_hash_ops) < 0) - return log_oom(); + if (u->manager) { + if (hashmap_ensure_allocated(&u->manager->exec_shared_runtime_by_id, &string_hash_ops) < 0) + return log_oom(); - rt = hashmap_get(u->manager->exec_shared_runtime_by_id, u->id); + rt = hashmap_get(u->manager->exec_shared_runtime_by_id, u->id); + } if (!rt) { if (exec_shared_runtime_allocate(&rt_create, u->id) < 0) return log_oom(); @@ -6875,7 +6863,7 @@ int exec_shared_runtime_deserialize_compat(Unit *u, const char *key, const char return 0; /* If the object is newly created, then put it to the hashmap which manages ExecSharedRuntime objects. */ - if (rt_create) { + if (rt_create && u->manager) { r = hashmap_put(u->manager->exec_shared_runtime_by_id, rt_create->id, rt_create); if (r < 0) { log_unit_debug_errno(u, r, "Failed to put runtime parameter to manager's storage: %m"); @@ -7101,8 +7089,11 @@ void exec_params_clear(ExecParameters *p) { p->environment = strv_free(p->environment); p->fd_names = strv_free(p->fd_names); + p->files_env = strv_free(p->files_env); p->fds = mfree(p->fds); p->exec_fd = safe_close(p->exec_fd); + p->user_lookup_fd = safe_close(p->user_lookup_fd); + p->bpf_outer_map_fd = -EBADF; } void exec_directory_done(ExecDirectory *d) { diff --git a/src/core/execute.h b/src/core/execute.h index 732d31969f2..52940332f75 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -427,6 +427,7 @@ struct ExecParameters { const char *received_encrypted_credentials_directory; const char *confirm_spawn; + bool shall_confirm_spawn; usec_t watchdog_usec; @@ -442,6 +443,12 @@ struct ExecParameters { const char *notify_socket; LIST_HEAD(OpenFile, open_files); + + const char *fallback_smack_process_label; + + char **files_env; + int user_lookup_fd; + int bpf_outer_map_fd; }; #include "unit.h" @@ -450,7 +457,7 @@ struct ExecParameters { int exec_spawn(Unit *unit, ExecCommand *command, const ExecContext *context, - const ExecParameters *exec_params, + ExecParameters *exec_params, ExecRuntime *runtime, const CGroupContext *cgroup_context, pid_t *ret); diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c index 76261a2d884..3d6af0d046b 100644 --- a/src/core/manager-serialize.c +++ b/src/core/manager-serialize.c @@ -507,7 +507,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { } } else if ((val = startswith(l, "dynamic-user="))) - dynamic_user_deserialize_one(m, val, fds); + dynamic_user_deserialize_one(m, val, fds, NULL); else if ((val = startswith(l, "destroy-ipc-uid="))) manager_deserialize_uid_refs_one(m, val); else if ((val = startswith(l, "destroy-ipc-gid="))) diff --git a/src/core/mount.c b/src/core/mount.c index 6424c56ed32..06a3b8a8c3c 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -890,11 +890,13 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { static int mount_spawn(Mount *m, ExecCommand *c, PidRef *ret_pid) { _cleanup_(exec_params_clear) ExecParameters exec_params = { - .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, - .stdin_fd = -EBADF, - .stdout_fd = -EBADF, - .stderr_fd = -EBADF, - .exec_fd = -EBADF, + .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -EBADF, + .stdout_fd = -EBADF, + .stderr_fd = -EBADF, + .exec_fd = -EBADF, + .bpf_outer_map_fd = -EBADF, + .user_lookup_fd = -EBADF, }; _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; pid_t pid; diff --git a/src/core/service.c b/src/core/service.c index 73a678b0cc1..802b1728de4 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1603,11 +1603,13 @@ static int service_spawn_internal( PidRef *ret_pid) { _cleanup_(exec_params_clear) ExecParameters exec_params = { - .flags = flags, - .stdin_fd = -EBADF, - .stdout_fd = -EBADF, - .stderr_fd = -EBADF, - .exec_fd = -EBADF, + .flags = flags, + .stdin_fd = -EBADF, + .stdout_fd = -EBADF, + .stderr_fd = -EBADF, + .exec_fd = -EBADF, + .bpf_outer_map_fd = -EBADF, + .user_lookup_fd = -EBADF, }; _cleanup_(sd_event_source_unrefp) sd_event_source *exec_fd_source = NULL; _cleanup_strv_free_ char **final_env = NULL, **our_env = NULL; diff --git a/src/core/socket.c b/src/core/socket.c index 1bbcadc3ba3..16faa256e2c 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1914,11 +1914,13 @@ static int socket_coldplug(Unit *u) { static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) { _cleanup_(exec_params_clear) ExecParameters exec_params = { - .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, - .stdin_fd = -EBADF, - .stdout_fd = -EBADF, - .stderr_fd = -EBADF, - .exec_fd = -EBADF, + .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -EBADF, + .stdout_fd = -EBADF, + .stderr_fd = -EBADF, + .exec_fd = -EBADF, + .bpf_outer_map_fd = -EBADF, + .user_lookup_fd = -EBADF, }; _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; pid_t pid; diff --git a/src/core/swap.c b/src/core/swap.c index 008c5bbc247..73db3fcb967 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -633,11 +633,13 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) { static int swap_spawn(Swap *s, ExecCommand *c, PidRef *ret_pid) { _cleanup_(exec_params_clear) ExecParameters exec_params = { - .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, - .stdin_fd = -EBADF, - .stdout_fd = -EBADF, - .stderr_fd = -EBADF, - .exec_fd = -EBADF, + .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -EBADF, + .stdout_fd = -EBADF, + .stderr_fd = -EBADF, + .exec_fd = -EBADF, + .bpf_outer_map_fd = -EBADF, + .user_lookup_fd = -EBADF, }; _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; pid_t pid; diff --git a/src/core/unit.c b/src/core/unit.c index 5623e949217..b028f8fda08 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -5393,6 +5393,22 @@ int unit_set_exec_params(Unit *u, ExecParameters *p) { p->received_credentials_directory = u->manager->received_credentials_directory; p->received_encrypted_credentials_directory = u->manager->received_encrypted_credentials_directory; + p->shall_confirm_spawn = !!u->manager->confirm_spawn; + + p->fallback_smack_process_label = u->manager->defaults.smack_process_label; + + if (u->manager->restrict_fs && p->bpf_outer_map_fd < 0) { + int fd = lsm_bpf_map_restrict_fs_fd(u); + if (fd < 0) + return fd; + + p->bpf_outer_map_fd = fd; + } + + p->user_lookup_fd = fcntl(u->manager->user_lookup_fds[1], F_DUPFD_CLOEXEC, 3); + if (p->user_lookup_fd < 0) + return -errno; + return 0; }