]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootctl: rework random seed logic to use open_mkdir_at() and openat()
authorLennart Poettering <lennart@poettering.net>
Mon, 19 Dec 2022 21:26:30 +0000 (22:26 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 4 Jan 2023 14:18:10 +0000 (15:18 +0100)
This doesn't really fix anything, but in general we should put stronger
emphasis on operating via dir fds rather than paths more (in particular
when writing files as opposed to consuming them).

No real change in behaviour.

src/boot/bootctl-random-seed.c

index f39a396a51d2518900b6a4f98f3968e9275dc32a..98ecc86aa5a2c1137c2d20178397266a35d5a4e8 100644 (file)
@@ -9,6 +9,7 @@
 #include "fd-util.h"
 #include "find-esp.h"
 #include "fs-util.h"
+#include "io-util.h"
 #include "mkdir.h"
 #include "path-util.h"
 #include "random-util.h"
 #include "umask-util.h"
 
 int install_random_seed(const char *esp) {
-        _cleanup_(unlink_and_freep) char *tmp = NULL;
+        _cleanup_close_ int esp_fd = -EBADF, loader_dir_fd = -EBADF, fd = -EBADF;
+        _cleanup_free_ char *tmp = NULL;
         uint8_t buffer[RANDOM_EFI_SEED_SIZE];
-        _cleanup_free_ char *path = NULL;
-        _cleanup_close_ int fd = -EBADF;
         size_t token_size;
-        ssize_t n;
         int r;
 
         assert(esp);
 
-        path = path_join(esp, "/loader/random-seed");
-        if (!path)
-                return log_oom();
+        esp_fd = open(esp, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
+        if (esp_fd < 0)
+                return log_error_errno(errno, "Failed to open ESP directory '%s': %m", esp);
+
+        loader_dir_fd = open_mkdir_at(esp_fd, "loader", O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOFOLLOW, 0775);
+        if (loader_dir_fd < 0)
+                return log_error_errno(loader_dir_fd, "Failed to open loader directory '%s/loader': %m", esp);
 
         r = crypto_random_bytes(buffer, sizeof(buffer));
         if (r < 0)
                 return log_error_errno(r, "Failed to acquire random seed: %m");
 
-        /* Normally create_subdirs() should already have created everything we need, but in case "bootctl
-         * random-seed" is called we want to just create the minimum we need for it, and not the full
-         * list. */
-        r = mkdir_parents(path, 0755);
-        if (r < 0)
-                return log_error_errno(r, "Failed to create parent directory for %s: %m", path);
-
-        r = tempfn_random(path, "bootctl", &tmp);
-        if (r < 0)
+        if (tempfn_random("random-seed", "bootctl", &tmp) < 0)
                 return log_oom();
 
-        fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|O_WRONLY|O_CLOEXEC, 0600);
-        if (fd < 0) {
-                tmp = mfree(tmp);
+        fd = openat(loader_dir_fd, tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|O_WRONLY|O_CLOEXEC, 0600);
+        if (fd < 0)
                 return log_error_errno(fd, "Failed to open random seed file for writing: %m");
-        }
 
-        n = write(fd, buffer, sizeof(buffer));
-        if (n < 0)
-                return log_error_errno(errno, "Failed to write random seed file: %m");
-        if ((size_t) n != sizeof(buffer))
-                return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while writing random seed file.");
+        r = loop_write(fd, buffer, sizeof(buffer), /* do_poll= */ false);
+        if (r < 0) {
+                log_error_errno(r, "Failed to write random seed file: %m");
+                goto fail;
+        }
 
-        if (rename(tmp, path) < 0)
-                return log_error_errno(errno, "Failed to move random seed file into place: %m");
+        if (renameat(loader_dir_fd, tmp, loader_dir_fd, "random-seed") < 0) {
+                r = log_error_errno(errno, "Failed to move random seed file into place: %m");
+                goto fail;
+        }
 
         tmp = mfree(tmp);
 
-        log_info("Random seed file %s successfully written (%zu bytes).", path, sizeof(buffer));
+        log_info("Random seed file %s/loader/random-seed successfully written (%zu bytes).", esp, sizeof(buffer));
 
         if (!arg_touch_variables)
                 return 0;
@@ -125,6 +120,12 @@ int install_random_seed(const char *esp) {
         }
 
         return 0;
+
+fail:
+        if (tmp)
+                (void) unlinkat(loader_dir_fd, tmp, 0);
+
+        return r;
 }
 
 int verb_random_seed(int argc, char *argv[], void *userdata) {