From: Daan De Meyer Date: Fri, 24 Mar 2023 13:30:16 +0000 (+0100) Subject: core: Move DynamicCreds into ExecRuntime X-Git-Tag: v254-rc1~874^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F26968%2Fhead;p=thirdparty%2Fsystemd.git core: Move DynamicCreds into ExecRuntime This is just another piece of runtime data so let's store it in ExecRuntime alongside the other runtime data. --- diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index 3824ae747fd..19cf3faca6c 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -739,18 +739,28 @@ int dynamic_user_lookup_name(Manager *m, const char *name, uid_t *ret) { return r; } -int dynamic_creds_acquire(DynamicCreds *creds, Manager *m, const char *user, const char *group) { +int dynamic_creds_make(Manager *m, const char *user, const char *group, DynamicCreds **ret) { + _cleanup_(dynamic_creds_unrefp) DynamicCreds *creds = NULL; bool acquired = false; int r; - assert(creds); assert(m); + assert(ret); + + if (!user && !group) { + *ret = NULL; + return 0; + } + + creds = new0(DynamicCreds, 1); + if (!creds) + return -ENOMEM; /* A DynamicUser object encapsulates an allocation of both a UID and a GID for a specific name. However, some * services use different user and groups. For cases like that there's DynamicCreds containing a pair of user * and group. This call allocates a pair. */ - if (!creds->user && user) { + if (user) { r = dynamic_user_acquire(m, user, &creds->user); if (r < 0) return r; @@ -758,20 +768,19 @@ int dynamic_creds_acquire(DynamicCreds *creds, Manager *m, const char *user, con acquired = true; } - if (!creds->group) { - - if (creds->user && (!group || streq_ptr(user, group))) - creds->group = dynamic_user_ref(creds->user); - else if (group) { - r = dynamic_user_acquire(m, group, &creds->group); - if (r < 0) { - if (acquired) - creds->user = dynamic_user_unref(creds->user); - return r; - } + if (creds->user && (!group || streq_ptr(user, group))) + creds->group = dynamic_user_ref(creds->user); + else if (group) { + r = dynamic_user_acquire(m, group, &creds->group); + if (r < 0) { + if (acquired) + creds->user = dynamic_user_unref(creds->user); + return r; } } + *ret = TAKE_PTR(creds); + return 0; } @@ -803,16 +812,22 @@ int dynamic_creds_realize(DynamicCreds *creds, char **suggested_paths, uid_t *ui return 0; } -void dynamic_creds_unref(DynamicCreds *creds) { - assert(creds); +DynamicCreds* dynamic_creds_unref(DynamicCreds *creds) { + if (!creds) + return NULL; creds->user = dynamic_user_unref(creds->user); creds->group = dynamic_user_unref(creds->group); + + return mfree(creds); } -void dynamic_creds_destroy(DynamicCreds *creds) { - assert(creds); +DynamicCreds* dynamic_creds_destroy(DynamicCreds *creds) { + if (!creds) + return NULL; creds->user = dynamic_user_destroy(creds->user); creds->group = dynamic_user_destroy(creds->group); + + return mfree(creds); } diff --git a/src/core/dynamic-user.h b/src/core/dynamic-user.h index 847ef475ca5..6539d17571b 100644 --- a/src/core/dynamic-user.h +++ b/src/core/dynamic-user.h @@ -33,8 +33,11 @@ int dynamic_user_current(DynamicUser *d, uid_t *ret); int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret); int dynamic_user_lookup_name(Manager *m, const char *name, uid_t *ret); -int dynamic_creds_acquire(DynamicCreds *creds, Manager *m, const char *user, const char *group); +int dynamic_creds_make(Manager *m, const char *user, const char *group, DynamicCreds **ret); int dynamic_creds_realize(DynamicCreds *creds, char **suggested_paths, uid_t *uid, gid_t *gid); -void dynamic_creds_unref(DynamicCreds *creds); -void dynamic_creds_destroy(DynamicCreds *creds); +DynamicCreds *dynamic_creds_unref(DynamicCreds *creds); +DynamicCreds *dynamic_creds_destroy(DynamicCreds *creds); + +DEFINE_TRIVIAL_CLEANUP_FUNC(DynamicCreds*, dynamic_creds_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(DynamicCreds*, dynamic_creds_destroy); diff --git a/src/core/execute.c b/src/core/execute.c index 86cfe99e8ba..81e48f12c6b 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -4057,7 +4057,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, - const DynamicCreds *dcreds, int user_lookup_fd, int socket_fd, const int *fds, size_t n_fds) { @@ -4086,11 +4085,11 @@ static int close_remaining_fds( append_socket_pair(dont_close, &n_dont_close, runtime->shared->ipcns_storage_socket); } - if (dcreds) { - if (dcreds->user) - append_socket_pair(dont_close, &n_dont_close, dcreds->user->storage_socket); - if (dcreds->group) - append_socket_pair(dont_close, &n_dont_close, dcreds->group->storage_socket); + if (runtime && runtime->dynamic_creds) { + if (runtime->dynamic_creds->user) + append_socket_pair(dont_close, &n_dont_close, runtime->dynamic_creds->user->storage_socket); + if (runtime->dynamic_creds->group) + append_socket_pair(dont_close, &n_dont_close, runtime->dynamic_creds->group->storage_socket); } if (user_lookup_fd >= 0) @@ -4404,7 +4403,6 @@ static int exec_child( const ExecContext *context, const ExecParameters *params, ExecRuntime *runtime, - DynamicCreds *dcreds, const CGroupContext *cgroup_context, int socket_fd, const int named_iofds[static 3], @@ -4537,7 +4535,7 @@ static int exec_child( } #endif - r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, keep_fds, n_keep_fds); + r = close_remaining_fds(params, runtime, user_lookup_fd, 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"); @@ -4583,7 +4581,7 @@ static int exec_child( return log_unit_error_errno(unit, errno, "Failed to update environment: %m"); } - if (context->dynamic_user && dcreds) { + if (context->dynamic_user && runtime && runtime->dynamic_creds) { _cleanup_strv_free_ char **suggested_paths = NULL; /* On top of that, make sure we bypass our own NSS module nss-systemd comprehensively for any NSS @@ -4599,7 +4597,7 @@ static int exec_child( return log_oom(); } - r = dynamic_creds_realize(dcreds, suggested_paths, &uid, &gid); + r = dynamic_creds_realize(runtime->dynamic_creds, suggested_paths, &uid, &gid); if (r < 0) { *exit_status = EXIT_USER; if (r == -EILSEQ) @@ -4618,8 +4616,8 @@ static int exec_child( return log_unit_error_errno(unit, SYNTHETIC_ERRNO(ESRCH), "GID validation failed for \""GID_FMT"\"", gid); } - if (dcreds->user) - username = dcreds->user->name; + if (runtime->dynamic_creds->user) + username = runtime->dynamic_creds->user->name; } else { r = get_fixed_user(context, &username, &uid, &gid, &home, &shell); @@ -5550,7 +5548,6 @@ int exec_spawn(Unit *unit, const ExecContext *context, const ExecParameters *params, ExecRuntime *runtime, - DynamicCreds *dcreds, const CGroupContext *cgroup_context, pid_t *ret) { @@ -5640,7 +5637,6 @@ int exec_spawn(Unit *unit, context, params, runtime, - dcreds, cgroup_context, socket_fd, named_iofds, @@ -7439,12 +7435,12 @@ void exec_shared_runtime_vacuum(Manager *m) { } } -int exec_runtime_make(ExecSharedRuntime *shared, ExecRuntime **ret) { +int exec_runtime_make(ExecSharedRuntime *shared, DynamicCreds *creds, ExecRuntime **ret) { _cleanup_(exec_runtime_freep) ExecRuntime *rt = NULL; assert(ret); - if (!shared) { + if (!shared && !creds) { *ret = NULL; return 0; } @@ -7455,6 +7451,7 @@ int exec_runtime_make(ExecSharedRuntime *shared, ExecRuntime **ret) { *rt = (ExecRuntime) { .shared = shared, + .dynamic_creds = creds, }; *ret = TAKE_PTR(rt); @@ -7466,6 +7463,7 @@ ExecRuntime* exec_runtime_free(ExecRuntime *rt) { return NULL; exec_shared_runtime_unref(rt->shared); + dynamic_creds_unref(rt->dynamic_creds); return mfree(rt); } @@ -7474,6 +7472,7 @@ ExecRuntime* exec_runtime_destroy(ExecRuntime *rt) { return NULL; rt->shared = exec_shared_runtime_destroy(rt->shared); + rt->dynamic_creds = dynamic_creds_destroy(rt->dynamic_creds); return exec_runtime_free(rt); } diff --git a/src/core/execute.h b/src/core/execute.h index 32ed912f157..254a1ee2d13 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -5,6 +5,7 @@ typedef struct ExecStatus ExecStatus; typedef struct ExecCommand ExecCommand; typedef struct ExecContext ExecContext; typedef struct ExecSharedRuntime ExecSharedRuntime; +typedef struct DynamicCreds DynamicCreds; typedef struct ExecRuntime ExecRuntime; typedef struct ExecParameters ExecParameters; typedef struct Manager Manager; @@ -127,6 +128,7 @@ struct ExecSharedRuntime { struct ExecRuntime { ExecSharedRuntime *shared; + DynamicCreds *dynamic_creds; }; typedef enum ExecDirectoryType { @@ -445,7 +447,6 @@ int exec_spawn(Unit *unit, const ExecContext *context, const ExecParameters *exec_params, ExecRuntime *runtime, - DynamicCreds *dynamic_creds, const CGroupContext *cgroup_context, pid_t *ret); @@ -498,7 +499,7 @@ int exec_shared_runtime_deserialize_compat(Unit *u, const char *key, const char int exec_shared_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds); void exec_shared_runtime_vacuum(Manager *m); -int exec_runtime_make(ExecSharedRuntime *shared, ExecRuntime **ret); +int exec_runtime_make(ExecSharedRuntime *shared, DynamicCreds *creds, ExecRuntime **ret); ExecRuntime* exec_runtime_free(ExecRuntime *rt); DEFINE_TRIVIAL_CLEANUP_FUNC(ExecRuntime*, exec_runtime_free); ExecRuntime* exec_runtime_destroy(ExecRuntime *rt); diff --git a/src/core/mount.c b/src/core/mount.c index a8a677a5310..586151bf67b 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -258,8 +258,6 @@ static void mount_done(Unit *u) { exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX); m->control_command = NULL; - dynamic_creds_unref(&m->dynamic_creds); - mount_unwatch_control_pid(m); m->timer_event_source = sd_event_source_disable_unref(m->timer_event_source); @@ -790,10 +788,8 @@ static int mount_coldplug(Unit *u) { return r; } - if (!IN_SET(m->deserialized_state, MOUNT_DEAD, MOUNT_FAILED)) { - (void) unit_setup_dynamic_creds(u); + if (!IN_SET(m->deserialized_state, MOUNT_DEAD, MOUNT_FAILED)) (void) unit_setup_exec_runtime(u); - } mount_set_state(m, m->deserialized_state); return 0; @@ -922,7 +918,6 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { &m->exec_context, &exec_params, m->exec_runtime, - &m->dynamic_creds, &m->cgroup_context, &pid); if (r < 0) @@ -954,8 +949,6 @@ static void mount_enter_dead(Mount *m, MountResult f) { unit_unref_uid_gid(UNIT(m), true); - dynamic_creds_destroy(&m->dynamic_creds); - /* Any dependencies based on /proc/self/mountinfo are now stale. Let's re-generate dependencies from * .mount unit. */ (void) mount_add_non_exec_dependencies(m); @@ -2268,7 +2261,6 @@ const UnitVTable mount_vtable = { .cgroup_context_offset = offsetof(Mount, cgroup_context), .kill_context_offset = offsetof(Mount, kill_context), .exec_runtime_offset = offsetof(Mount, exec_runtime), - .dynamic_creds_offset = offsetof(Mount, dynamic_creds), .sections = "Unit\0" diff --git a/src/core/mount.h b/src/core/mount.h index 1a0d9fc5e59..d6d6d335a45 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -76,7 +76,6 @@ struct Mount { CGroupContext cgroup_context; ExecRuntime *exec_runtime; - DynamicCreds dynamic_creds; MountState state, deserialized_state; diff --git a/src/core/service.c b/src/core/service.c index 883c4bbd933..cfce4594a06 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -388,8 +388,6 @@ static void service_done(Unit *u) { s->control_command = NULL; s->main_command = NULL; - dynamic_creds_unref(&s->dynamic_creds); - exit_status_set_free(&s->restart_prevent_status); exit_status_set_free(&s->restart_force_status); exit_status_set_free(&s->success_status); @@ -1267,7 +1265,6 @@ static int service_coldplug(Unit *u) { if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART, SERVICE_CLEANING)) { (void) unit_enqueue_rewatch_pids(u); - (void) unit_setup_dynamic_creds(u); (void) unit_setup_exec_runtime(u); } @@ -1719,7 +1716,6 @@ static int service_spawn_internal( &s->exec_context, &exec_params, s->exec_runtime, - &s->dynamic_creds, &s->cgroup_context, &pid); if (r < 0) @@ -1933,9 +1929,6 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) /* Get rid of the IPC bits of the user */ unit_unref_uid_gid(UNIT(s), true); - /* Release the user, and destroy it if we are the only remaining owner */ - dynamic_creds_destroy(&s->dynamic_creds); - /* Try to delete the pid file. At this point it will be * out-of-date, and some software might be confused by it, so * let's remove it. */ @@ -4894,7 +4887,6 @@ const UnitVTable service_vtable = { .cgroup_context_offset = offsetof(Service, cgroup_context), .kill_context_offset = offsetof(Service, kill_context), .exec_runtime_offset = offsetof(Service, exec_runtime), - .dynamic_creds_offset = offsetof(Service, dynamic_creds), .sections = "Unit\0" diff --git a/src/core/service.h b/src/core/service.h index 7663f26f70a..1517b818679 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -156,7 +156,6 @@ struct Service { /* Runtime data of the execution context */ ExecRuntime *exec_runtime; - DynamicCreds dynamic_creds; pid_t main_pid, control_pid; diff --git a/src/core/socket.c b/src/core/socket.c index 163fc0bebf8..af6603df07c 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -154,8 +154,6 @@ static void socket_done(Unit *u) { exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); s->control_command = NULL; - dynamic_creds_unref(&s->dynamic_creds); - socket_unwatch_control_pid(s); unit_ref_unset(&s->service); @@ -1908,10 +1906,8 @@ static int socket_coldplug(Unit *u) { return r; } - if (!IN_SET(s->deserialized_state, SOCKET_DEAD, SOCKET_FAILED, SOCKET_CLEANING)) { - (void) unit_setup_dynamic_creds(u); + if (!IN_SET(s->deserialized_state, SOCKET_DEAD, SOCKET_FAILED, SOCKET_CLEANING)) (void) unit_setup_exec_runtime(u); - } socket_set_state(s, s->deserialized_state); return 0; @@ -1950,7 +1946,6 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { &s->exec_context, &exec_params, s->exec_runtime, - &s->dynamic_creds, &s->cgroup_context, &pid); if (r < 0) @@ -2057,8 +2052,6 @@ static void socket_enter_dead(Socket *s, SocketResult f) { unit_destroy_runtime_data(UNIT(s), &s->exec_context); unit_unref_uid_gid(UNIT(s), true); - - dynamic_creds_destroy(&s->dynamic_creds); } static void socket_enter_signal(Socket *s, SocketState state, SocketResult f); @@ -3471,7 +3464,6 @@ const UnitVTable socket_vtable = { .cgroup_context_offset = offsetof(Socket, cgroup_context), .kill_context_offset = offsetof(Socket, kill_context), .exec_runtime_offset = offsetof(Socket, exec_runtime), - .dynamic_creds_offset = offsetof(Socket, dynamic_creds), .sections = "Unit\0" diff --git a/src/core/socket.h b/src/core/socket.h index 6813bdcf8c8..308a0727568 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -91,7 +91,6 @@ struct Socket { CGroupContext cgroup_context; ExecRuntime *exec_runtime; - DynamicCreds dynamic_creds; /* For Accept=no sockets refers to the one service we'll * activate. For Accept=yes sockets is either NULL, or filled diff --git a/src/core/swap.c b/src/core/swap.c index 17f8123055c..c6e2c8b1bd9 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -174,8 +174,6 @@ static void swap_done(Unit *u) { exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX); s->control_command = NULL; - dynamic_creds_unref(&s->dynamic_creds); - swap_unwatch_control_pid(s); s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source); @@ -593,10 +591,8 @@ static int swap_coldplug(Unit *u) { return r; } - if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED)) { - (void) unit_setup_dynamic_creds(u); + if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED)) (void) unit_setup_exec_runtime(u); - } swap_set_state(s, new_state); return 0; @@ -689,7 +685,6 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { &s->exec_context, &exec_params, s->exec_runtime, - &s->dynamic_creds, &s->cgroup_context, &pid); if (r < 0) @@ -724,8 +719,6 @@ static void swap_enter_dead(Swap *s, SwapResult f) { unit_destroy_runtime_data(UNIT(s), &s->exec_context); unit_unref_uid_gid(UNIT(s), true); - - dynamic_creds_destroy(&s->dynamic_creds); } static void swap_enter_active(Swap *s, SwapResult f) { @@ -1619,7 +1612,6 @@ const UnitVTable swap_vtable = { .cgroup_context_offset = offsetof(Swap, cgroup_context), .kill_context_offset = offsetof(Swap, kill_context), .exec_runtime_offset = offsetof(Swap, exec_runtime), - .dynamic_creds_offset = offsetof(Swap, dynamic_creds), .sections = "Unit\0" diff --git a/src/core/swap.h b/src/core/swap.h index c0e3f118e18..d61c7112cf6 100644 --- a/src/core/swap.h +++ b/src/core/swap.h @@ -68,7 +68,6 @@ struct Swap { CGroupContext cgroup_context; ExecRuntime *exec_runtime; - DynamicCreds dynamic_creds; SwapState state, deserialized_state; diff --git a/src/core/unit.c b/src/core/unit.c index e569a82e1ce..e3a57e3b843 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -4792,7 +4792,9 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) int unit_setup_exec_runtime(Unit *u) { _cleanup_(exec_shared_runtime_unrefp) ExecSharedRuntime *esr = NULL; + _cleanup_(dynamic_creds_unrefp) DynamicCreds *dcreds = NULL; ExecRuntime **rt; + ExecContext *ec; size_t offset; Unit *other; int r; @@ -4805,6 +4807,9 @@ int unit_setup_exec_runtime(Unit *u) { if (*rt) return 0; + ec = unit_get_exec_context(u); + assert(ec); + /* Try to get it from somebody else */ UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_JOINS_NAMESPACE_OF) { r = exec_shared_runtime_acquire(u->manager, NULL, other->id, false, &esr); @@ -4815,40 +4820,27 @@ int unit_setup_exec_runtime(Unit *u) { } if (!esr) { - r = exec_shared_runtime_acquire(u->manager, unit_get_exec_context(u), u->id, true, &esr); + r = exec_shared_runtime_acquire(u->manager, ec, u->id, true, &esr); if (r < 0) return r; } - r = exec_runtime_make(esr, rt); + if (ec->dynamic_user) { + r = dynamic_creds_make(u->manager, ec->user, ec->group, &dcreds); + if (r < 0) + return r; + } + + r = exec_runtime_make(esr, dcreds, rt); if (r < 0) return r; TAKE_PTR(esr); + TAKE_PTR(dcreds); return r; } -int unit_setup_dynamic_creds(Unit *u) { - ExecContext *ec; - DynamicCreds *dcreds; - size_t offset; - - assert(u); - - offset = UNIT_VTABLE(u)->dynamic_creds_offset; - assert(offset > 0); - dcreds = (DynamicCreds*) ((uint8_t*) u + offset); - - ec = unit_get_exec_context(u); - assert(ec); - - if (!ec->dynamic_user) - return 0; - - return dynamic_creds_acquire(dcreds, u->manager, ec->user, ec->group); -} - bool unit_type_supported(UnitType t) { static int8_t cache[_UNIT_TYPE_MAX] = {}; /* -1: disabled, 1: enabled: 0: don't know */ int r; @@ -5580,10 +5572,6 @@ int unit_prepare_exec(Unit *u) { if (r < 0) return r; - r = unit_setup_dynamic_creds(u); - if (r < 0) - return r; - return 0; } diff --git a/src/core/unit.h b/src/core/unit.h index bf9aea578ac..513c8181f57 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -574,10 +574,6 @@ typedef struct UnitVTable { * that */ size_t exec_runtime_offset; - /* If greater than 0, the offset into the object where the pointer to DynamicCreds is found, if the unit type - * has that. */ - size_t dynamic_creds_offset; - /* The name of the configuration file section with the private settings of this unit */ const char *private_section; @@ -967,7 +963,6 @@ CGroupContext *unit_get_cgroup_context(Unit *u) _pure_; ExecRuntime *unit_get_exec_runtime(Unit *u) _pure_; int unit_setup_exec_runtime(Unit *u); -int unit_setup_dynamic_creds(Unit *u); char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf); char* unit_concat_strv(char **l, UnitWriteFlags flags);