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.
This commit is contained in:
Mike Yuan
2026-02-10 21:54:11 +01:00
parent 7c358751a4
commit bae58ceff7
3 changed files with 93 additions and 89 deletions
+92 -87
View 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);
-1
View 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);
+1 -1
View 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");