]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/exec-credential: use struct load_cred_args everywhere
authorMike Yuan <me@yhndnzj.com>
Wed, 31 Jul 2024 17:44:25 +0000 (19:44 +0200)
committerMike Yuan <me@yhndnzj.com>
Sun, 4 Aug 2024 04:51:28 +0000 (06:51 +0200)
We currently duplicate the same set of params for every funcs.
Let's unify this, and make things more manageable.

src/core/exec-credential.c

index 1ab667c37144f2ce1a97187214a04560bbe6ad38..e06fc21c315a75032031d4a29c46516f89ac7e46 100644 (file)
@@ -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;
         }