From: Mike Yuan Date: Sun, 14 Dec 2025 07:56:35 +0000 (+0100) Subject: core/exec-credential: only pass needed bits of ExecParameters down in exec_setup_cred... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bae58ceff7c7a10280017a64b12ff097dba48147;p=thirdparty%2Fsystemd.git core/exec-credential: only pass needed bits of ExecParameters down in exec_setup_credentials() No functional change, preparation for credential reloading support, where we'd operate on Unit rather than ExecParameters. --- diff --git a/src/core/exec-credential.c b/src/core/exec-credential.c index 83ed112471e..3766096a416 100644 --- a/src/core/exec-credential.c +++ b/src/core/exec-credential.c @@ -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); diff --git a/src/core/exec-credential.h b/src/core/exec-credential.h index 056e5173588..e7e60a9e024 100644 --- a/src/core/exec-credential.h +++ b/src/core/exec-credential.h @@ -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); diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index a0c101a662d..a0b0a87a659 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -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");