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,
_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);
* 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;
}
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;
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,
}
static int maybe_decrypt_and_write_credential(
- struct load_cred_args *args,
+ LoadCredentialArguments *args,
const char *id,
const char *data,
size_t size,
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
flags |= CREDENTIAL_ANY_SCOPE;
- if (!args->always_ipc) {
+ if (!args->context->always_ipc) {
r = decrypt_credential_and_warn(
id,
now(CLOCK_REALTIME),
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);
}
static int load_credential_glob(
- struct load_cred_args *args,
+ LoadCredentialArguments *args,
const ExecImportCredential *ic,
char * const *search_path,
ReadFullFileFlags flags) {
}
static int load_credential(
- struct load_cred_args *args,
+ LoadCredentialArguments *args,
const char *id,
int read_dfd,
const char *path) {
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);
/* 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;
* 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;
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
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;
}
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;
/* 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;
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;
/* 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) {
}
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;
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;
if (r < 0 && r != -EEXIST)
return r;
- workspace = path_join(t, unit);
+ workspace = path_join(t, context->unit);
if (!workspace)
return -ENOMEM;
(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;
/* 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");
}
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);
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
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;
}
}
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");
(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");
const ExecContext *context,
const CGroupContext *cgroup_context,
const ExecParameters *params,
- const char *unit,
uid_t uid,
gid_t gid) {
assert(context);
assert(params);
- assert(unit);
if (!exec_params_need_credentials(params) || !exec_context_has_credentials(context))
return 0;
if (r < 0 && r != -EEXIST)
return r;
- p = path_join(q, unit);
+ p = path_join(q, params->unit_id);
if (!p)
return -ENOMEM;
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);