diff --git a/src/core/execute.c b/src/core/execute.c index 128ed6471f..437d517b71 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2598,7 +2598,9 @@ static int write_credential( static int load_credential( const ExecContext *context, const ExecParameters *params, - ExecLoadCredential *lc, + const char *id, + const char *path, + bool encrypted, const char *unit, int read_dfd, int write_dfd, @@ -2606,12 +2608,6 @@ static int load_credential( bool ownership_ok, uint64_t *left) { - assert(context); - assert(lc); - assert(unit); - assert(write_dfd >= 0); - assert(left); - ReadFullFileFlags flags = READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER; _cleanup_(erase_and_freep) char *data = NULL; _cleanup_free_ char *j = NULL, *bindname = NULL; @@ -2620,14 +2616,22 @@ static int load_credential( size_t size, add; int r; - if (path_is_absolute(lc->path) || read_dfd >= 0) { + assert(context); + assert(params); + assert(id); + assert(path); + assert(unit); + assert(write_dfd >= 0); + assert(left); + + if (path_is_absolute(path) || read_dfd >= 0) { /* If this is an absolute path, read the data directly from it, and support AF_UNIX sockets */ - source = lc->path; + source = path; flags |= READ_FULL_FILE_CONNECT_SOCKET; /* 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, lc->id) < 0) + if (asprintf(&bindname, "@%" PRIx64"/unit/%s/%s", random_u64(), unit, id) < 0) return -ENOMEM; missing_ok = false; @@ -2636,7 +2640,7 @@ static int load_credential( /* If this is a relative path, take it relative to the credentials 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. */ - j = path_join(params->received_credentials, lc->path); + j = path_join(params->received_credentials, path); if (!j) return -ENOMEM; @@ -2648,14 +2652,14 @@ static int load_credential( r = read_full_file_full( read_dfd, source, UINT64_MAX, - lc->encrypted ? CREDENTIAL_ENCRYPTED_SIZE_MAX : CREDENTIAL_SIZE_MAX, - flags | (lc->encrypted ? READ_FULL_FILE_UNBASE64 : 0), + encrypted ? CREDENTIAL_ENCRYPTED_SIZE_MAX : CREDENTIAL_SIZE_MAX, + flags | (encrypted ? READ_FULL_FILE_UNBASE64 : 0), bindname, &data, &size); else r = -ENOENT; - if (r == -ENOENT && (missing_ok || hashmap_contains(context->set_credentials, lc->id))) { + if (r == -ENOENT && (missing_ok || hashmap_contains(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 @@ -2663,17 +2667,17 @@ static int load_credential( * * Also, if the source file doesn't exist, but a fallback is set via SetCredentials= * we are fine, too. */ - log_debug_errno(r, "Couldn't read inherited credential '%s', skipping: %m", lc->path); + log_debug_errno(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", lc->path); + return log_debug_errno(r, "Failed to read credential '%s': %m", path); - if (lc->encrypted) { + if (encrypted) { _cleanup_free_ void *plaintext = NULL; size_t plaintext_size = 0; - r = decrypt_credential_and_warn(lc->id, now(CLOCK_REALTIME), NULL, data, size, &plaintext, &plaintext_size); + r = decrypt_credential_and_warn(id, now(CLOCK_REALTIME), NULL, data, size, &plaintext, &plaintext_size); if (r < 0) return r; @@ -2681,11 +2685,11 @@ static int load_credential( size = plaintext_size; } - add = strlen(lc->id) + size; + add = strlen(id) + size; if (add > *left) return -E2BIG; - r = write_credential(write_dfd, lc->id, data, size, uid, ownership_ok); + r = write_credential(write_dfd, id, data, size, uid, ownership_ok); if (r < 0) return r; @@ -2695,10 +2699,9 @@ static int load_credential( struct load_cred_args { Set *seen_creds; - const ExecContext *context; const ExecParameters *params; - ExecLoadCredential *parent_local_credential; + ExecLoadCredential *parent_load_credential; const char *unit; int dfd; uid_t uid; @@ -2729,7 +2732,7 @@ static int load_cred_recurse_dir_cb( if (!credname) return -ENOMEM; - sub_id = strjoin(args->parent_local_credential->id, "_", credname); + sub_id = strjoin(args->parent_load_credential->id, "_", credname); if (!sub_id) return -ENOMEM; @@ -2745,12 +2748,18 @@ static int load_cred_recurse_dir_cb( if (r < 0) return r; - r = load_credential(args->context, args->params, - &(ExecLoadCredential) { - .id = sub_id, - .path = (char *) de->d_name, - .encrypted = args->parent_local_credential->encrypted, - }, args->unit, dir_fd, args->dfd, args->uid, args->ownership_ok, args->left); + r = load_credential( + args->context, + args->params, + sub_id, + de->d_name, + args->parent_load_credential->encrypted, + args->unit, + dir_fd, + args->dfd, + args->uid, + args->ownership_ok, + args->left); if (r < 0) return r; @@ -2797,14 +2806,30 @@ static int acquire_credentials( return -errno; if (sub_fd < 0) { + /* Regular file */ + r = set_put_strdup(&seen_creds, lc->id); if (r < 0) return r; - r = load_credential(context, params, lc, unit, -1, dfd, uid, ownership_ok, &left); + + r = load_credential( + context, + params, + lc->id, + lc->path, + lc->encrypted, + unit, + -1, + dfd, + uid, + ownership_ok, + &left); if (r < 0) return r; } else { + /* Directory */ + r = recurse_dir( sub_fd, /* path= */ "", @@ -2816,7 +2841,7 @@ static int acquire_credentials( .seen_creds = seen_creds, .context = context, .params = params, - .parent_local_credential = lc, + .parent_load_credential = lc, .unit = unit, .dfd = dfd, .uid = uid,