]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: ensure execute/spawn functions can work without manager object
authorLuca Boccassi <bluca@debian.org>
Thu, 31 Aug 2023 20:08:49 +0000 (21:08 +0100)
committerLuca Boccassi <bluca@debian.org>
Thu, 12 Oct 2023 12:37:22 +0000 (13:37 +0100)
When switching to serialization later, the Manager object will not be
serialized, move parameters around instead

13 files changed:
src/core/bpf-lsm.c
src/core/bpf-lsm.h
src/core/cgroup.c
src/core/dynamic-user.c
src/core/dynamic-user.h
src/core/execute.c
src/core/execute.h
src/core/manager-serialize.c
src/core/mount.c
src/core/service.c
src/core/socket.c
src/core/swap.c
src/core/unit.c

index 22200bd939360907190af3c33c5fb2f499b5e5b0..300486597b3eead37d4dc3c018b643e6d050dde4 100644 (file)
@@ -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");
 }
 
index dff581279d7fdef94a692d4ed03a903a17c7e737..5eb03ae7fb4682219711f27328dc088e4e1b8b16 100644 (file)
@@ -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);
index 47bab04f4210681ec8be87614046cfd06ca28620..69c9d9a9bbeb638afa0fd83a0841b65043c0c9da 100644 (file)
@@ -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,
index e99a6694f6f6f34ca65798614fb03b9677d0c18d..2cab0d44acb713b87b89160380904591967f9b54 100644 (file)
@@ -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) {
index 6539d17571b2112afc2ca3e587a1caefdf4b3396..679c588a76dffae52cb790a3aeb00f86ba0ae9c3 100644 (file)
@@ -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);
index a45da470bd0cfd47c04e03467d14dc2b2dc35994..e305e7b8be6d49b12b4f438b81aa0b06d95ff3e7 100644 (file)
@@ -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 *)&params->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, &params->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) {
index 732d31969f22b19b3ed5e84809468d95be2d0c8d..52940332f757423b6b5a280c256a0efc85bd586f 100644 (file)
@@ -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);
index 76261a2d8840b3d0e56b47437f17bed4e21c04f7..3d6af0d046b1ae5f5aedb8b058e68090e67d5862 100644 (file)
@@ -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=")))
index 6424c56ed32ba4ef21fb9e813cef16fe32303655..06a3b8a8c3cac5190f9c1531d3fa2e8c40232557 100644 (file)
@@ -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;
index 73a678b0cc1d3baad7dfda8970734a40796968f1..802b1728de4e05fd53e10f44dff1a43403dff153 100644 (file)
@@ -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;
index 1bbcadc3ba3008b84bcdcedd87cb9f708fb7dcaf..16faa256e2cfad8ad4a7239f6be4361169b8380d 100644 (file)
@@ -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;
index 008c5bbc247a180b6656d6094c85e84306256b46..73db3fcb967bc353d26150823309a216ed563e27 100644 (file)
@@ -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;
index 5623e949217cad770730c93989984803b9af3102..b028f8fda0801cef0f9912f4a957fb23babc0916 100644 (file)
@@ -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;
 }