diff options
author | Mike Yuan <me@yhndnzj.com> | 2024-07-31 19:44:25 +0200 |
---|---|---|
committer | Mike Yuan <me@yhndnzj.com> | 2024-08-04 06:51:28 +0200 |
commit | 85b265c96403a148be5207b7da17f9cc1867e04c (patch) | |
tree | 434c4df409d3365b586c4f4ff87b029ea35fd654 /src | |
parent | core/exec-credential: use maybe_decrypt_and_write_credential() for SetCred= too (diff) | |
download | systemd-85b265c96403a148be5207b7da17f9cc1867e04c.tar.xz systemd-85b265c96403a148be5207b7da17f9cc1867e04c.zip |
core/exec-credential: use struct load_cred_args everywhere
We currently duplicate the same set of params for every funcs.
Let's unify this, and make things more manageable.
Diffstat (limited to 'src')
-rw-r--r-- | src/core/exec-credential.c | 211 |
1 files changed, 82 insertions, 129 deletions
diff --git a/src/core/exec-credential.c b/src/core/exec-credential.c index 1ab667c371..e06fc21c31 100644 --- a/src/core/exec-credential.c +++ b/src/core/exec-credential.c @@ -403,26 +403,34 @@ static char** credential_search_path(const ExecParameters *params, CredentialSea return TAKE_PTR(l); } +struct load_cred_args { + const ExecContext *context; + const ExecParameters *params; + const char *unit; + bool encrypted; + int write_dfd; + uid_t uid; + gid_t gid; + bool ownership_ok; + uint64_t left; +}; + static int maybe_decrypt_and_write_credential( - int dir_fd, + struct load_cred_args *args, const char *id, - bool encrypted, - uid_t uid, - gid_t gid, - bool ownership_ok, const char *data, - size_t size, - uint64_t *left) { + size_t size) { _cleanup_(iovec_done_erase) struct iovec plaintext = {}; size_t add; int r; - assert(dir_fd >= 0); + assert(args); + assert(args->write_dfd >= 0); assert(id); - assert(left); + assert(data || size == 0); - if (encrypted) { + if (args->encrypted) { r = decrypt_credential_and_warn( id, now(CLOCK_REALTIME), @@ -440,34 +448,30 @@ static int maybe_decrypt_and_write_credential( } add = strlen(id) + size; - if (add > *left) + if (add > args->left) return -E2BIG; - r = write_credential(dir_fd, id, data, size, uid, gid, ownership_ok); + r = write_credential(args->write_dfd, id, data, size, args->uid, args->gid, args->ownership_ok); if (r < 0) return log_debug_errno(r, "Failed to write credential '%s': %m", id); - *left -= add; + args->left -= add; + return 0; } static int load_credential_glob( + struct load_cred_args *args, const ExecImportCredential *ic, - bool encrypted, char * const *search_path, - ReadFullFileFlags flags, - int write_dfd, - uid_t uid, - gid_t gid, - bool ownership_ok, - uint64_t *left) { + ReadFullFileFlags flags) { int r; + assert(args); + assert(args->write_dfd >= 0); assert(ic); assert(search_path); - assert(write_dfd >= 0); - assert(left); STRV_FOREACH(d, search_path) { _cleanup_globfree_ glob_t pglob = {}; @@ -507,7 +511,7 @@ static int load_credential_glob( continue; } - if (faccessat(write_dfd, fn, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) { + if (faccessat(args->write_dfd, fn, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) { log_debug("Skipping credential with duplicated ID %s at %s", fn, *p); continue; } @@ -519,22 +523,14 @@ static int load_credential_glob( AT_FDCWD, *p, UINT64_MAX, - encrypted ? CREDENTIAL_ENCRYPTED_SIZE_MAX : CREDENTIAL_SIZE_MAX, + args->encrypted ? CREDENTIAL_ENCRYPTED_SIZE_MAX : CREDENTIAL_SIZE_MAX, flags, NULL, &data, &size); if (r < 0) return log_debug_errno(r, "Failed to read credential '%s': %m", *p); - r = maybe_decrypt_and_write_credential( - write_dfd, - fn, - encrypted, - uid, - gid, - ownership_ok, - data, size, - left); + r = maybe_decrypt_and_write_credential(args, fn, data, size); if (r < 0) return r; } @@ -544,18 +540,10 @@ static int load_credential_glob( } static int load_credential( - const ExecContext *context, - const ExecParameters *params, + struct load_cred_args *args, const char *id, - const char *path, - bool encrypted, - const char *unit, int read_dfd, - int write_dfd, - uid_t uid, - gid_t gid, - bool ownership_ok, - uint64_t *left) { + const char *path) { ReadFullFileFlags flags = READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER; _cleanup_strv_free_ char **search_path = NULL; @@ -566,14 +554,14 @@ static int load_credential( size_t size, maxsz; int r; - assert(context); - assert(params); + assert(args); + assert(args->context); + assert(args->params); + assert(args->unit); + assert(args->write_dfd >= 0); assert(id); - assert(path); - assert(unit); assert(read_dfd >= 0 || read_dfd == AT_FDCWD); - assert(write_dfd >= 0); - assert(left); + assert(path); if (read_dfd >= 0) { /* If a directory fd is specified, then read the file directly from that dir. In this case we @@ -598,7 +586,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(), unit, id) < 0) + if (asprintf(&bindname, "@%" PRIx64 "/unit/%s/%s", random_u64(), args->unit, id) < 0) return -ENOMEM; missing_ok = false; @@ -609,7 +597,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. */ - search_path = credential_search_path(params, CREDENTIAL_SEARCH_PATH_ALL); + search_path = credential_search_path(args->params, CREDENTIAL_SEARCH_PATH_ALL); if (!search_path) return -ENOMEM; @@ -617,10 +605,11 @@ static int load_credential( } else source = NULL; - if (encrypted) + if (args->encrypted) { flags |= READ_FULL_FILE_UNBASE64; - - maxsz = encrypted ? CREDENTIAL_ENCRYPTED_SIZE_MAX : CREDENTIAL_SIZE_MAX; + maxsz = CREDENTIAL_ENCRYPTED_SIZE_MAX; + } else + maxsz = CREDENTIAL_SIZE_MAX; if (search_path) STRV_FOREACH(d, search_path) { @@ -651,7 +640,7 @@ static int load_credential( else r = -ENOENT; - if (r == -ENOENT && (missing_ok || hashmap_contains(context->set_credentials, id))) { + if (r == -ENOENT && (missing_ok || hashmap_contains(args->context->set_credentials, id))) { /* 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 * themselves will get ENOENT when trying to read them, which should not be much @@ -659,28 +648,16 @@ static int load_credential( * * Also, if the source file doesn't exist, but a fallback is set via SetCredentials= * we are fine, too. */ - log_full_errno(hashmap_contains(context->set_credentials, id) ? LOG_DEBUG : LOG_INFO, + log_full_errno(hashmap_contains(args->context->set_credentials, id) ? LOG_DEBUG : LOG_INFO, r, "Couldn't read inherited credential '%s', skipping: %m", path); return 0; } if (r < 0) return log_debug_errno(r, "Failed to read credential '%s': %m", path); - return maybe_decrypt_and_write_credential(write_dfd, id, encrypted, uid, gid, ownership_ok, data, size, left); + return maybe_decrypt_and_write_credential(args, id, data, size); } -struct load_cred_args { - const ExecContext *context; - const ExecParameters *params; - bool encrypted; - const char *unit; - int dfd; - uid_t uid; - gid_t gid; - bool ownership_ok; - uint64_t *left; -}; - static int load_cred_recurse_dir_cb( RecurseDirEvent event, const char *path, @@ -710,26 +687,16 @@ static int load_cred_recurse_dir_cb( if (!credential_name_valid(sub_id)) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Credential would get ID '%s', which is not valid, refusing.", sub_id); - if (faccessat(args->dfd, sub_id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) { + if (faccessat(args->write_dfd, sub_id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) { log_debug("Skipping credential with duplicated ID %s at %s", sub_id, path); return RECURSE_DIR_CONTINUE; } if (errno != ENOENT) return log_debug_errno(errno, "Failed to test if credential %s exists: %m", sub_id); - r = load_credential( - args->context, - args->params, - sub_id, - de->d_name, - args->encrypted, - args->unit, - dir_fd, - args->dfd, - args->uid, - args->gid, - args->ownership_ok, - args->left); + r = load_credential(args, + sub_id, + dir_fd, de->d_name); if (r < 0) return r; @@ -745,7 +712,6 @@ static int acquire_credentials( gid_t gid, bool ownership_ok) { - uint64_t left = CREDENTIALS_TOTAL_SIZE_MAX; _cleanup_close_ int dfd = -EBADF; int r; @@ -762,11 +728,24 @@ static int acquire_credentials( if (r < 0) return r; + struct load_cred_args args = { + .context = context, + .params = params, + .unit = unit, + .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) { _cleanup_close_ int sub_fd = -EBADF; + args.encrypted = lc->encrypted; + /* If this is an absolute path, then try to open it as a directory. If that works, then we'll * recurse into it. If it is an absolute path but it isn't a directory, then we'll open it as * a regular file. Finally, if it's a relative path we will use it as a credential name to @@ -782,19 +761,9 @@ static int acquire_credentials( if (sub_fd < 0) /* Regular file (incl. a credential passed in from higher up) */ - r = load_credential( - context, - params, - lc->id, - lc->path, - lc->encrypted, - unit, - AT_FDCWD, - dfd, - uid, - gid, - ownership_ok, - &left); + r = load_credential(&args, + lc->id, + AT_FDCWD, lc->path); else /* Directory */ r = recurse_dir(sub_fd, @@ -803,17 +772,7 @@ static int acquire_credentials( /* n_depth_max= */ UINT_MAX, RECURSE_DIR_SORT|RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE, load_cred_recurse_dir_cb, - &(struct load_cred_args) { - .context = context, - .params = params, - .encrypted = lc->encrypted, - .unit = unit, - .dfd = dfd, - .uid = uid, - .gid = gid, - .ownership_ok = ownership_ok, - .left = &left, - }); + &args); if (r < 0) return r; } @@ -828,16 +787,12 @@ static int acquire_credentials( if (!search_path) return -ENOMEM; - r = load_credential_glob( - ic, - /* encrypted = */ false, - search_path, - READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER, - dfd, - uid, - gid, - ownership_ok, - &left); + args.encrypted = false; + + r = load_credential_glob(&args, + ic, + search_path, + READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER); if (r < 0) return r; @@ -846,16 +801,12 @@ static int acquire_credentials( if (!search_path) return -ENOMEM; - r = load_credential_glob( - ic, - /* encrypted = */ true, - search_path, - READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER|READ_FULL_FILE_UNBASE64, - dfd, - uid, - gid, - ownership_ok, - &left); + args.encrypted = true; + + r = load_credential_glob(&args, + ic, + search_path, + READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER|READ_FULL_FILE_UNBASE64); if (r < 0) return r; } @@ -864,6 +815,8 @@ static int acquire_credentials( * 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) { + args.encrypted = sc->encrypted; + if (faccessat(dfd, sc->id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) { log_debug("Skipping credential with duplicated ID %s", sc->id); continue; @@ -871,7 +824,7 @@ static int acquire_credentials( if (errno != ENOENT) return log_debug_errno(errno, "Failed to test if credential %s exists: %m", sc->id); - r = maybe_decrypt_and_write_credential(dfd, sc->id, sc->encrypted, uid, gid, ownership_ok, sc->data, sc->size, &left); + r = maybe_decrypt_and_write_credential(&args, sc->id, sc->data, sc->size); if (r < 0) return r; } |