]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/exec-credential: only pass needed bits of ExecParameters down in exec_setup_cred...
authorMike Yuan <me@yhndnzj.com>
Sun, 14 Dec 2025 07:56:35 +0000 (08:56 +0100)
committerMike Yuan <me@yhndnzj.com>
Tue, 10 Feb 2026 20:54:11 +0000 (21:54 +0100)
No functional change, preparation for credential reloading support,
where we'd operate on Unit rather than ExecParameters.

src/core/exec-credential.c
src/core/exec-credential.h
src/core/exec-invoke.c

index 83ed112471e9c957eebda40e784e7d11ddb37a67..3766096a4165c225268be0879270c2cbdbd9d214 100644 (file)
@@ -310,6 +310,34 @@ int exec_context_destroy_credentials(const ExecContext *c, const char *runtime_p
         return 0;
 }
 
+typedef struct SetupCredentialsContext {
+        RuntimeScope scope;
+
+        const ExecContext *exec_context;
+        const char *unit;
+
+        const char *runtime_prefix;
+
+        const char *received_credentials_directory;
+        const char *received_encrypted_credentials_directory;
+
+        bool always_ipc;
+
+        uid_t uid;
+        gid_t gid;
+} SetupCredentialsContext;
+
+typedef struct LoadCredentialArguments {
+        const SetupCredentialsContext *context;
+
+        bool encrypted;
+
+        int write_dfd;
+        bool ownership_ok;
+
+        uint64_t left;
+} LoadCredentialArguments;
+
 typedef enum CredentialSearchPath {
         CREDENTIAL_SEARCH_PATH_TRUSTED,
         CREDENTIAL_SEARCH_PATH_ENCRYPTED,
@@ -318,11 +346,15 @@ typedef enum CredentialSearchPath {
         _CREDENTIAL_SEARCH_PATH_INVALID = -EINVAL,
 } CredentialSearchPath;
 
-static int credential_search_path(const ExecParameters *params, CredentialSearchPath path, char ***ret) {
+static int credential_search_path(
+                const SetupCredentialsContext *context,
+                CredentialSearchPath path,
+                char ***ret) {
+
         _cleanup_strv_free_ char **l = NULL;
         int r;
 
-        assert(params);
+        assert(context);
         assert(path >= 0 && path < _CREDENTIAL_SEARCH_PATH_MAX);
         assert(ret);
 
@@ -331,12 +363,12 @@ static int credential_search_path(const ExecParameters *params, CredentialSearch
          * credentials, we'll look in /etc/credstore.encrypted/ (and similar dirs). */
 
         if (IN_SET(path, CREDENTIAL_SEARCH_PATH_ENCRYPTED, CREDENTIAL_SEARCH_PATH_ALL)) {
-                r = strv_extend(&l, params->received_encrypted_credentials_directory);
+                r = strv_extend(&l, context->received_encrypted_credentials_directory);
                 if (r < 0)
                         return r;
 
                 _cleanup_strv_free_ char **add = NULL;
-                r = credential_store_path_encrypted(params->runtime_scope, &add);
+                r = credential_store_path_encrypted(context->scope, &add);
                 if (r < 0)
                         return r;
 
@@ -346,12 +378,12 @@ static int credential_search_path(const ExecParameters *params, CredentialSearch
         }
 
         if (IN_SET(path, CREDENTIAL_SEARCH_PATH_TRUSTED, CREDENTIAL_SEARCH_PATH_ALL)) {
-                r = strv_extend(&l, params->received_credentials_directory);
+                r = strv_extend(&l, context->received_credentials_directory);
                 if (r < 0)
                         return r;
 
                 _cleanup_strv_free_ char **add = NULL;
-                r = credential_store_path(params->runtime_scope, &add);
+                r = credential_store_path(context->scope, &add);
                 if (r < 0)
                         return r;
 
@@ -369,23 +401,6 @@ static int credential_search_path(const ExecParameters *params, CredentialSearch
         return 0;
 }
 
-struct load_cred_args {
-        const ExecContext *context;
-        const ExecParameters *params;
-        const char *unit;
-
-        bool always_ipc;
-
-        bool encrypted;
-
-        int write_dfd;
-        uid_t uid;
-        gid_t gid;
-        bool ownership_ok;
-
-        uint64_t left;
-};
-
 static int write_credential(
                 int dfd,
                 const char *id,
@@ -431,7 +446,7 @@ static int write_credential(
 }
 
 static int maybe_decrypt_and_write_credential(
-                struct load_cred_args *args,
+                LoadCredentialArguments *args,
                 const char *id,
                 const char *data,
                 size_t size,
@@ -449,7 +464,7 @@ static int maybe_decrypt_and_write_credential(
         if (args->encrypted) {
                 CredentialFlags flags = 0; /* only allow user creds in user scope */
 
-                switch (args->params->runtime_scope) {
+                switch (args->context->scope) {
 
                 case RUNTIME_SCOPE_SYSTEM:
                         /* In system mode talk directly to the TPM – unless we live in a device sandbox
@@ -457,7 +472,7 @@ static int maybe_decrypt_and_write_credential(
 
                         flags |= CREDENTIAL_ANY_SCOPE;
 
-                        if (!args->always_ipc) {
+                        if (!args->context->always_ipc) {
                                 r = decrypt_credential_and_warn(
                                                 id,
                                                 now(CLOCK_REALTIME),
@@ -506,7 +521,7 @@ static int maybe_decrypt_and_write_credential(
         if (add > args->left)
                 return -E2BIG;
 
-        r = write_credential(args->write_dfd, id, data, size, args->uid, args->gid, args->ownership_ok);
+        r = write_credential(args->write_dfd, id, data, size, args->context->uid, args->context->gid, args->ownership_ok);
         if (r < 0)
                 return log_debug_errno(r, "Failed to write credential '%s': %m", id);
 
@@ -516,7 +531,7 @@ static int maybe_decrypt_and_write_credential(
 }
 
 static int load_credential_glob(
-                struct load_cred_args *args,
+                LoadCredentialArguments *args,
                 const ExecImportCredential *ic,
                 char * const *search_path,
                 ReadFullFileFlags flags) {
@@ -595,7 +610,7 @@ static int load_credential_glob(
 }
 
 static int load_credential(
-                struct load_cred_args *args,
+                LoadCredentialArguments *args,
                 const char *id,
                 int read_dfd,
                 const char *path) {
@@ -611,9 +626,8 @@ static int load_credential(
 
         assert(args);
         assert(args->context);
-        assert(args->params);
-        assert(args->unit);
-        assert(args->write_dfd >= 0);
+        assert(args->context->exec_context);
+        assert(args->context->unit);
         assert(id);
         assert(read_dfd >= 0 || read_dfd == AT_FDCWD);
         assert(path);
@@ -641,7 +655,7 @@ static int load_credential(
 
                 /* Pass some minimal info about the unit and the credential name we are looking to acquire
                  * via the source socket address in case we read off an AF_UNIX socket. */
-                if (asprintf(&bindname, "@%" PRIx64 "/unit/%s/%s", random_u64(), args->unit, id) < 0)
+                if (asprintf(&bindname, "@%" PRIx64 "/unit/%s/%s", random_u64(), args->context->unit, id) < 0)
                         return -ENOMEM;
 
                 missing_ok = false;
@@ -652,7 +666,7 @@ static int load_credential(
                  * directory we received ourselves. We don't support the AF_UNIX stuff in this mode, since we
                  * are operating on a credential store, i.e. this is guaranteed to be regular files. */
 
-                r = credential_search_path(args->params, CREDENTIAL_SEARCH_PATH_ALL, &search_path);
+                r = credential_search_path(args->context, CREDENTIAL_SEARCH_PATH_ALL, &search_path);
                 if (r < 0)
                         return r;
 
@@ -696,7 +710,7 @@ static int load_credential(
                 assert_not_reached();
 
         if (r == -ENOENT) {
-                bool in_set_credentials = hashmap_contains(args->context->set_credentials, id);
+                bool in_set_credentials = hashmap_contains(args->context->exec_context->set_credentials, id);
                 if (missing_ok || in_set_credentials) {
                         /* Make a missing inherited credential non-fatal, let's just continue. After all apps
                          * will get clear errors if we don't pass such a missing credential on as they
@@ -725,7 +739,7 @@ static int load_cred_recurse_dir_cb(
                 const struct statx *sx,
                 void *userdata) {
 
-        struct load_cred_args *args = ASSERT_PTR(userdata);
+        LoadCredentialArguments *args = ASSERT_PTR(userdata);
         _cleanup_free_ char *sub_id = NULL;
         int r;
 
@@ -782,38 +796,27 @@ static bool device_nodes_restricted(
 }
 
 static int acquire_credentials(
-                const ExecContext *context,
-                const CGroupContext *cgroup_context,
-                const ExecParameters *params,
-                const char *unit,
+                const SetupCredentialsContext *context,
                 int dfd,
-                uid_t uid,
-                gid_t gid,
                 bool ownership_ok) {
 
         int r;
 
         assert(context);
-        assert(cgroup_context);
-        assert(params);
-        assert(unit);
+        assert(context->exec_context);
         assert(dfd >= 0);
 
-        struct load_cred_args args = {
+        LoadCredentialArguments args = {
                 .context = context,
-                .params = params,
-                .unit = unit,
-                .always_ipc = device_nodes_restricted(context, cgroup_context),
+
                 .write_dfd = dfd,
-                .uid = uid,
-                .gid = gid,
                 .ownership_ok = ownership_ok,
                 .left = CREDENTIALS_TOTAL_SIZE_MAX,
         };
 
         /* First, load credentials off disk (or acquire via AF_UNIX socket) */
         ExecLoadCredential *lc;
-        HASHMAP_FOREACH(lc, context->load_credentials) {
+        HASHMAP_FOREACH(lc, context->exec_context->load_credentials) {
                 _cleanup_close_ int sub_fd = -EBADF;
 
                 args.encrypted = lc->encrypted;
@@ -852,10 +855,10 @@ static int acquire_credentials(
         /* Next, look for system credentials and credentials in the credentials store. Note that these do not
          * override any credentials found earlier. */
         ExecImportCredential *ic;
-        ORDERED_SET_FOREACH(ic, context->import_credentials) {
+        ORDERED_SET_FOREACH(ic, context->exec_context->import_credentials) {
                 _cleanup_free_ char **search_path = NULL;
 
-                r = credential_search_path(params, CREDENTIAL_SEARCH_PATH_TRUSTED, &search_path);
+                r = credential_search_path(context, CREDENTIAL_SEARCH_PATH_TRUSTED, &search_path);
                 if (r < 0)
                         return r;
 
@@ -871,7 +874,7 @@ static int acquire_credentials(
 
                 search_path = strv_free(search_path);
 
-                r = credential_search_path(params, CREDENTIAL_SEARCH_PATH_ENCRYPTED, &search_path);
+                r = credential_search_path(context, CREDENTIAL_SEARCH_PATH_ENCRYPTED, &search_path);
                 if (r < 0)
                         return r;
 
@@ -889,7 +892,7 @@ static int acquire_credentials(
         /* Finally, we add in literally specified credentials. If the credentials already exist, we'll not
          * add them, so that they can act as a "default" if the same credential is specified multiple times. */
         ExecSetCredential *sc;
-        HASHMAP_FOREACH(sc, context->set_credentials) {
+        HASHMAP_FOREACH(sc, context->exec_context->set_credentials) {
                 args.encrypted = sc->encrypted;
 
                 if (faccessat(dfd, sc->id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) {
@@ -937,13 +940,8 @@ static int credentials_dir_finalize_permissions(int dfd, uid_t uid, gid_t gid, b
 }
 
 static int setup_credentials_plain_dir(
-                const ExecContext *context,
-                const CGroupContext *cgroup_context,
-                const ExecParameters *params,
-                const char *unit,
-                const char *cred_dir,
-                uid_t uid,
-                gid_t gid) {
+                const SetupCredentialsContext *context,
+                const char *cred_dir) {
 
         _cleanup_free_ char *t = NULL, *workspace = NULL;
         _cleanup_(rm_rf_safep) const char *workspace_rm = NULL;
@@ -951,13 +949,13 @@ static int setup_credentials_plain_dir(
         int r;
 
         assert(context);
-        assert(params);
-        assert(unit);
+        assert(context->unit);
+        assert(context->runtime_prefix);
         assert(cred_dir);
 
         /* Temporary workspace, that remains inaccessible all the time. We prepare stuff there before moving
          * it into place, so that users can't access half-initialized credential stores. */
-        t = path_join(params->prefix[EXEC_DIRECTORY_RUNTIME], "systemd/temporary-credentials");
+        t = path_join(context->runtime_prefix, "systemd/temporary-credentials");
         if (!t)
                 return -ENOMEM;
 
@@ -965,7 +963,7 @@ static int setup_credentials_plain_dir(
         if (r < 0 && r != -EEXIST)
                 return r;
 
-        workspace = path_join(t, unit);
+        workspace = path_join(t, context->unit);
         if (!workspace)
                 return -ENOMEM;
 
@@ -976,7 +974,7 @@ static int setup_credentials_plain_dir(
 
         (void) label_fix_full(dfd, /* inode_path= */ NULL, cred_dir, /* flags= */ 0);
 
-        r = acquire_credentials(context, cgroup_context, params, unit, dfd, uid, gid, /* ownership_ok= */ false);
+        r = acquire_credentials(context, dfd, /* ownership_ok= */ false);
         if (r < 0)
                 return r;
 
@@ -998,7 +996,7 @@ static int setup_credentials_plain_dir(
 
         /* rename() requires both the source and target to be writable, hence lock down write permission
          * as last step. */
-        r = credentials_dir_finalize_permissions(dfd, uid, gid, /* ownership_ok= */ false);
+        r = credentials_dir_finalize_permissions(dfd, context->uid, context->gid, /* ownership_ok= */ false);
         if (r < 0)
                 return log_debug_errno(r, "Failed to adjust ACLs of credentials dir: %m");
 
@@ -1006,21 +1004,15 @@ static int setup_credentials_plain_dir(
 }
 
 static int setup_credentials_internal(
-                const ExecContext *context,
-                const CGroupContext *cgroup_context,
-                const ExecParameters *params,
-                const char *unit,
-                const char *cred_dir,
-                uid_t uid,
-                gid_t gid) {
+                const SetupCredentialsContext *context,
+                bool may_reuse,
+                const char *cred_dir) {
 
         _cleanup_close_ int fs_fd = -EBADF, mfd = -EBADF, dfd = -EBADF;
         bool dir_mounted;
         int r;
 
         assert(context);
-        assert(params);
-        assert(unit);
         assert(cred_dir);
 
         r = path_is_mount_point(cred_dir);
@@ -1028,7 +1020,7 @@ static int setup_credentials_internal(
                 return log_debug_errno(r, "Failed to determine if '%s' is a mountpoint: %m", cred_dir);
         dir_mounted = r > 0;
 
-        if (!FLAGS_SET(params->flags, EXEC_SETUP_CREDENTIALS_FRESH)) {
+        if (may_reuse) {
                 bool populated;
 
                 /* If the cred dir is a mount, let's treat it as populated, and only look at the contents
@@ -1044,7 +1036,7 @@ static int setup_credentials_internal(
                         populated = r == 0;
                 }
                 if (populated) {
-                        log_debug("Credential dir for unit '%s' already set up, skipping.", unit);
+                        log_debug("Credential dir for unit '%s' already set up, skipping.", context->unit);
                         return 0;
                 }
         }
@@ -1052,7 +1044,7 @@ static int setup_credentials_internal(
         mfd = fsmount_credentials_fs(&fs_fd);
         if (ERRNO_IS_NEG_PRIVILEGE(mfd) && !dir_mounted) {
                 log_debug_errno(mfd, "Lacking privilege to mount credentials fs, falling back to plain directory.");
-                return setup_credentials_plain_dir(context, cgroup_context, params, unit, cred_dir, uid, gid);
+                return setup_credentials_plain_dir(context, cred_dir);
         }
         if (mfd < 0)
                 return log_debug_errno(mfd, "Failed to mount credentials fs: %m");
@@ -1063,11 +1055,11 @@ static int setup_credentials_internal(
 
         (void) label_fix_full(dfd, /* inode_path= */ NULL, cred_dir, /* flags= */ 0);
 
-        r = acquire_credentials(context, cgroup_context, params, unit, dfd, uid, gid, /* ownership_ok= */ true);
+        r = acquire_credentials(context, dfd, /* ownership_ok= */ true);
         if (r < 0)
                 return r;
 
-        r = credentials_dir_finalize_permissions(dfd, uid, gid, /* ownership_ok= */ true);
+        r = credentials_dir_finalize_permissions(dfd, context->uid, context->gid, /* ownership_ok= */ true);
         if (r < 0)
                 return log_debug_errno(r, "Failed to adjust ACLs of credentials dir: %m");
 
@@ -1112,7 +1104,6 @@ int exec_setup_credentials(
                 const ExecContext *context,
                 const CGroupContext *cgroup_context,
                 const ExecParameters *params,
-                const char *unit,
                 uid_t uid,
                 gid_t gid) {
 
@@ -1121,7 +1112,6 @@ int exec_setup_credentials(
 
         assert(context);
         assert(params);
-        assert(unit);
 
         if (!exec_params_need_credentials(params) || !exec_context_has_credentials(context))
                 return 0;
@@ -1139,7 +1129,7 @@ int exec_setup_credentials(
         if (r < 0 && r != -EEXIST)
                 return r;
 
-        p = path_join(q, unit);
+        p = path_join(q, params->unit_id);
         if (!p)
                 return -ENOMEM;
 
@@ -1147,7 +1137,22 @@ int exec_setup_credentials(
         if (r < 0 && r != -EEXIST)
                 return r;
 
-        r = setup_credentials_internal(context, cgroup_context, params, unit, p, uid, gid);
+        SetupCredentialsContext ctx = {
+                .scope = params->runtime_scope,
+                .exec_context = context,
+                .unit = params->unit_id,
+
+                .runtime_prefix = params->prefix[EXEC_DIRECTORY_RUNTIME],
+                .received_credentials_directory = params->received_credentials_directory,
+                .received_encrypted_credentials_directory = params->received_encrypted_credentials_directory,
+
+                .always_ipc = device_nodes_restricted(context, cgroup_context),
+
+                .uid = uid,
+                .gid = gid,
+        };
+
+        r = setup_credentials_internal(&ctx, /* may_reuse = */ !FLAGS_SET(params->flags, EXEC_SETUP_CREDENTIALS_FRESH), p);
         if (r < 0)
                 (void) rmdir(p);
 
index 056e517358879422326fe4bcc2fc4644b7e3de66..e7e60a9e024104d7625fa3085601678c99888a80 100644 (file)
@@ -57,7 +57,6 @@ int exec_setup_credentials(
                 const ExecContext *context,
                 const CGroupContext *cgroup_context,
                 const ExecParameters *params,
-                const char *unit,
                 uid_t uid,
                 gid_t gid);
 
index a0c101a662d88a28486c5566c3a2df9fb5f0b4fa..a0b0a87a659e61ee18967d6de1e88854776875b1 100644 (file)
@@ -5705,7 +5705,7 @@ int exec_invoke(
                         return log_error_errno(r, "Failed to set up special execution directory in %s: %m", params->prefix[dt]);
         }
 
-        r = exec_setup_credentials(context, cgroup_context, params, params->unit_id, uid, gid);
+        r = exec_setup_credentials(context, cgroup_context, params, uid, gid);
         if (r < 0) {
                 *exit_status = EXIT_CREDENTIALS;
                 return log_error_errno(r, "Failed to set up credentials: %m");