]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
find-esp: return pinned fd to ESP/XBOOTLDR 41658/head
authorLennart Poettering <lennart@amutable.com>
Mon, 13 Apr 2026 16:04:29 +0000 (18:04 +0200)
committerLennart Poettering <lennart@amutable.com>
Mon, 20 Apr 2026 15:19:27 +0000 (17:19 +0200)
The reworks the ESP/XBOOTLDR logic to pin the ESP/XBOOTLDR via an fd,
and return that as optional return parameter.

So far we only pinned the parent dir of the ESP/XBOOTLDR, which was
useful when verifying that ESP/XBOOTLDR is actually a mount point by
comparing mount ids. This however became obsolete with
a98a6eb95cc980edab4b0f9c59e6573edc7ffe0c. Hence, let's clean this up,
and pin the inode we really care about and return it.

16 files changed:
src/bless-boot/bless-boot.c
src/bootctl/bootctl-cleanup.c
src/bootctl/bootctl-install.c
src/bootctl/bootctl-random-seed.c
src/bootctl/bootctl-random-seed.h
src/bootctl/bootctl-status.c
src/bootctl/bootctl-unlink.c
src/bootctl/bootctl.c
src/bootctl/bootctl.h
src/kernel-install/kernel-install.c
src/shared/bootspec.c
src/shared/creds-util.c
src/shared/find-esp.c
src/shared/find-esp.h
src/sysupdate/sysupdate-resource.c
src/tpm2-setup/tpm2-swtpm.c

index 86525f359a102afa2f581b0aefccb1b6925c6c53..33fbdbb7608323ccfc9352f9e416552691e4183c 100644 (file)
@@ -115,6 +115,7 @@ static int acquire_path(void) {
                         /* path= */ NULL,
                         /* unprivileged_mode= */ false,
                         &esp_path,
+                        /* ret_fd= */ NULL,
                         /* ret_part= */ NULL,
                         /* ret_pstart= */ NULL,
                         /* ret_psize= */ NULL,
@@ -128,6 +129,7 @@ static int acquire_path(void) {
                         /* path= */ NULL,
                         /* unprivileged_mode= */ false,
                         &xbootldr_path,
+                        /* ret_fd= */ NULL,
                         /* ret_uuid= */ NULL,
                         &xbootldr_devid);
         if (r < 0 && r != -ENOKEY)
index e654bca10497c88d1870667ee7042e9c904c2ee5..1e8819bea18134eb1820da641a4c20496cb4329d 100644 (file)
@@ -93,6 +93,7 @@ int verb_cleanup(int argc, char *argv[], uintptr_t _data, void *userdata) {
 
         r = acquire_esp(/* unprivileged_mode= */ false,
                         /* graceful= */ false,
+                        /* ret_fd= */ NULL,
                         /* ret_part= */ NULL,
                         /* ret_pstart= */ NULL,
                         /* ret_psize= */ NULL,
@@ -103,6 +104,7 @@ int verb_cleanup(int argc, char *argv[], uintptr_t _data, void *userdata) {
 
         r = acquire_xbootldr(
                         /* unprivileged_mode= */ false,
+                        /* ret_fd= */ NULL,
                         /* ret_uuid= */ NULL,
                         &xbootldr_devid);
         if (r < 0)
index fc89ce143b94bc5771dbbdb439c7de3f79d7286c..96bc9213cf6b24b17a5f9f49b1576d85df460573 100644 (file)
@@ -163,6 +163,7 @@ static int install_context_from_cmdline(
 
         r = acquire_esp(/* unprivileged_mode= */ false,
                         b.graceful,
+                        &b.esp_fd,
                         &b.esp_part,
                         &b.esp_pstart,
                         &b.esp_psize,
@@ -189,6 +190,7 @@ static int install_context_from_cmdline(
 
         r = acquire_xbootldr(
                         /* unprivileged_mode= */ false,
+                        &b.xbootldr_fd,
                         /* ret_uuid= */ NULL,
                         /* ret_devid= */ NULL);
         if (r < 0)
@@ -213,55 +215,16 @@ static int install_context_from_cmdline(
         return !!ret->esp_path; /* return positive if we found an ESP */
 }
 
-static int acquire_esp_fd(InstallContext *c) {
-        int r;
-
-        assert(c);
-
-        if (c->esp_fd >= 0)
-                return c->esp_fd;
-
-        assert(c->esp_path);
-
-        _cleanup_free_ char *j = path_join(c->root, c->esp_path);
-        if (!j)
-                return log_oom();
-
-        r = chaseat(c->root_fd,
-                    c->esp_path,
-                    CHASE_AT_RESOLVE_IN_ROOT|CHASE_TRIGGER_AUTOFS|CHASE_MUST_BE_DIRECTORY,
-                    /* ret_path= */ NULL,
-                    &c->esp_fd);
-        if (r < 0)
-                return log_error_errno(r, "Failed to open ESP '%s': %m", j);
-
-        return c->esp_fd;
-}
-
 static int acquire_dollar_boot_fd(InstallContext *c) {
-        int r;
-
         assert(c);
 
         if (c->xbootldr_fd >= 0)
                 return c->xbootldr_fd;
 
-        if (!c->xbootldr_path)
-                return acquire_esp_fd(c);
-
-        _cleanup_free_ char *j = path_join(c->root, c->xbootldr_path);
-        if (!j)
-                return log_oom();
-
-        r = chaseat(c->root_fd,
-                    c->xbootldr_path,
-                    CHASE_AT_RESOLVE_IN_ROOT|CHASE_TRIGGER_AUTOFS|CHASE_MUST_BE_DIRECTORY,
-                    /* ret_path= */ NULL,
-                    &c->xbootldr_fd);
-        if (r < 0)
-                return log_error_errno(r, "Failed to open XBOOTLDR '%s': %m", j);
+        if (c->esp_fd >= 0)
+                return c->esp_fd;
 
-        return c->xbootldr_fd;
+        return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Cannot access $BOOT, as neither ESP nor XBOOTLDR have been found.");
 }
 
 static const char* dollar_boot_path(InstallContext *c) {
@@ -639,9 +602,8 @@ static int update_efi_boot_binaries(
         assert(c);
         assert(source_path);
 
-        int esp_fd = acquire_esp_fd(c);
-        if (esp_fd < 0)
-                return esp_fd;
+        if (c->esp_fd < 0)
+                return c->esp_fd;
 
         _cleanup_free_ char *j = path_join(c->root, c->esp_path);
         if (!j)
@@ -649,7 +611,7 @@ static int update_efi_boot_binaries(
 
         _cleanup_closedir_ DIR *d = NULL;
         r = chase_and_opendirat(
-                        esp_fd,
+                        c->esp_fd,
                         "/EFI/BOOT",
                         CHASE_AT_RESOLVE_IN_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_MUST_BE_DIRECTORY,
                         /* ret_path= */ NULL,
@@ -738,16 +700,15 @@ static int copy_one_file(
                         return log_error_errno(source_fd, "Failed to resolve path '%s': %m", sp);
         }
 
-        int esp_fd = acquire_esp_fd(c);
-        if (esp_fd < 0)
-                return esp_fd;
+        if (c->esp_fd < 0)
+                return c->esp_fd;
 
         _cleanup_free_ char *j = path_join(c->root, c->esp_path);
         if (!j)
                 return log_oom();
 
         _cleanup_close_ int dest_parent_fd = -EBADF;
-        r = chaseat(esp_fd,
+        r = chaseat(c->esp_fd,
                     "/EFI/systemd",
                     CHASE_AT_RESOLVE_IN_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY,
                     /* ret_path= */ NULL,
@@ -778,7 +739,7 @@ static int copy_one_file(
                 ascii_strupper(boot_dot_efi);
 
                 _cleanup_close_ int default_dest_parent_fd = -EBADF;
-                r = chaseat(esp_fd,
+                r = chaseat(c->esp_fd,
                             "/EFI/BOOT",
                             CHASE_AT_RESOLVE_IN_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY,
                             /* ret_path= */ NULL,
@@ -875,16 +836,15 @@ static int install_loader_config(InstallContext *c) {
         assert(c);
         assert(c->make_entry_directory >= 0);
 
-        int esp_fd = acquire_esp_fd(c);
-        if (esp_fd < 0)
-                return esp_fd;
+        if (c->esp_fd < 0)
+                return c->esp_fd;
 
         _cleanup_free_ char *j = path_join(c->root, c->esp_path);
         if (!j)
                 return log_oom();
 
         _cleanup_close_ int loader_dir_fd = -EBADF;
-        r = chaseat(esp_fd,
+        r = chaseat(c->esp_fd,
                     "loader",
                     CHASE_AT_RESOLVE_IN_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY,
                     /* ret_path= */ NULL,
@@ -1071,16 +1031,15 @@ static int install_secure_boot_auto_enroll(InstallContext *c) {
                 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert X.509 certificate to DER: %s",
                                        ERR_error_string(ERR_get_error(), NULL));
 
-        int esp_fd = acquire_esp_fd(c);
-        if (esp_fd < 0)
-                return esp_fd;
+        if (c->esp_fd < 0)
+                return c->esp_fd;
 
         _cleanup_free_ char *j = path_join(c->root, c->esp_path);
         if (!j)
                 return log_oom();
 
         _cleanup_close_ int keys_fd = -EBADF;
-        r = chaseat(esp_fd,
+        r = chaseat(c->esp_fd,
                     "loader/keys/auto",
                     CHASE_AT_RESOLVE_IN_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY,
                     /* ret_path= */ NULL,
@@ -1385,16 +1344,15 @@ static int install_variables(
 
         assert(c);
 
-        int esp_fd = acquire_esp_fd(c);
-        if (esp_fd < 0)
-                return esp_fd;
+        if (c->esp_fd < 0)
+                return c->esp_fd;
 
         _cleanup_free_ char *j = path_join(c->root, c->esp_path);
         if (!j)
                 return log_oom();
 
         r = chase_and_accessat(
-                        esp_fd,
+                        c->esp_fd,
                         path,
                         CHASE_AT_RESOLVE_IN_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_MUST_BE_REGULAR,
                         F_OK,
@@ -1422,7 +1380,7 @@ static int install_variables(
         if (c->operation == INSTALL_NEW || !existing) {
                 _cleanup_free_ char *description = NULL;
 
-                r = pick_efi_boot_option_description(esp_fd, &description);
+                r = pick_efi_boot_option_description(c->esp_fd, &description);
                 if (r < 0)
                         return r;
 
@@ -1474,12 +1432,11 @@ static int are_we_installed(InstallContext *c) {
         if (!p)
                 return log_oom();
 
-        int esp_fd = acquire_esp_fd(c);
-        if (esp_fd < 0)
-                return esp_fd;
+        if (c->esp_fd < 0)
+                return c->esp_fd;
 
         _cleanup_close_ int fd = chase_and_openat(
-                        esp_fd,
+                        c->esp_fd,
                         "/EFI/systemd",
                         CHASE_AT_RESOLVE_IN_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_MUST_BE_DIRECTORY,
                         O_RDONLY|O_CLOEXEC|O_DIRECTORY,
@@ -1582,9 +1539,8 @@ static int run_install(InstallContext *c) {
 
         const char *arch = arg_arch_all ? "" : get_efi_arch();
 
-        int esp_fd = acquire_esp_fd(c);
-        if (esp_fd < 0)
-                return esp_fd;
+        if (c->esp_fd < 0)
+                return c->esp_fd;
 
         _cleanup_free_ char *j = path_join(c->root, c->esp_path);
         if (!j)
@@ -1604,7 +1560,7 @@ static int run_install(InstallContext *c) {
                          * we'll drop-in our files (unless there are newer ones already), but we won't create
                          * the directories for them in the first place. */
 
-                        r = create_subdirs(j, esp_fd, esp_subdirs);
+                        r = create_subdirs(j, c->esp_fd, esp_subdirs);
                         if (r < 0)
                                 return r;
 
@@ -1631,7 +1587,7 @@ static int run_install(InstallContext *c) {
                                 return r;
 
                         if (arg_install_random_seed && !c->root) {
-                                r = install_random_seed(c->esp_path);
+                                r = install_random_seed(c->esp_path, c->esp_fd);
                                 if (r < 0)
                                         return r;
                         }
@@ -1689,9 +1645,8 @@ static int remove_boot_efi(InstallContext *c) {
 
         assert(c);
 
-        int esp_fd = acquire_esp_fd(c);
-        if (esp_fd < 0)
-                return esp_fd;
+        if (c->esp_fd < 0)
+                return c->esp_fd;
 
         _cleanup_free_ char *w = path_join(c->root, c->esp_path);
         if (!w)
@@ -1700,7 +1655,7 @@ static int remove_boot_efi(InstallContext *c) {
         _cleanup_closedir_ DIR *d = NULL;
         _cleanup_free_ char *p = NULL;
         r = chase_and_opendirat(
-                        esp_fd,
+                        c->esp_fd,
                         "/EFI/BOOT",
                         CHASE_AT_RESOLVE_IN_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_MUST_BE_DIRECTORY,
                         &p,
@@ -1898,15 +1853,14 @@ int verb_remove(int argc, char *argv[], uintptr_t _data, void *userdata) {
         if (r < 0)
                 return r;
 
-        int esp_fd = acquire_esp_fd(&c);
-        if (esp_fd < 0)
-                return esp_fd;
+        if (c.esp_fd < 0)
+                return c.esp_fd;
 
         _cleanup_free_ char *j = path_join(c.root, c.esp_path);
         if (!j)
                 return log_oom();
 
-        int dollar_boot_fd = acquire_dollar_boot_fd(&c); /* this will initialize .xbootldr_fd */
+        int dollar_boot_fd = acquire_dollar_boot_fd(&c);
         if (dollar_boot_fd < 0)
                 return dollar_boot_fd;
 
@@ -1915,23 +1869,23 @@ int verb_remove(int argc, char *argv[], uintptr_t _data, void *userdata) {
                 return log_oom();
 
         r = remove_binaries(&c);
-        RET_GATHER(r, unlink_inode(j, esp_fd, "/loader/loader.conf", S_IFREG));
-        RET_GATHER(r, unlink_inode(j, esp_fd, "/loader/random-seed", S_IFREG));
-        RET_GATHER(r, unlink_inode(j, esp_fd, "/loader/entries.srel", S_IFREG));
+        RET_GATHER(r, unlink_inode(j, c.esp_fd, "/loader/loader.conf", S_IFREG));
+        RET_GATHER(r, unlink_inode(j, c.esp_fd, "/loader/random-seed", S_IFREG));
+        RET_GATHER(r, unlink_inode(j, c.esp_fd, "/loader/entries.srel", S_IFREG));
 
         FOREACH_STRING(db, "PK.auth", "KEK.auth", "db.auth") {
                 _cleanup_free_ char *p = path_join("/loader/keys/auto", db);
                 if (!p)
                         return log_oom();
 
-                RET_GATHER(r, unlink_inode(j, esp_fd, p, S_IFREG));
+                RET_GATHER(r, unlink_inode(j, c.esp_fd, p, S_IFREG));
         }
-        RET_GATHER(r, unlink_inode(j, esp_fd, "/loader/keys/auto", S_IFDIR));
-        RET_GATHER(r, unlink_inode(j, esp_fd, "/loader/entries.srel", S_IFREG));
+        RET_GATHER(r, unlink_inode(j, c.esp_fd, "/loader/keys/auto", S_IFDIR));
+        RET_GATHER(r, unlink_inode(j, c.esp_fd, "/loader/entries.srel", S_IFREG));
 
-        RET_GATHER(r, remove_subdirs(j, esp_fd, esp_subdirs));
-        RET_GATHER(r, remove_subdirs(j, esp_fd, dollar_boot_subdirs));
-        RET_GATHER(r, remove_entry_directory(&c, j, esp_fd));
+        RET_GATHER(r, remove_subdirs(j, c.esp_fd, esp_subdirs));
+        RET_GATHER(r, remove_subdirs(j, c.esp_fd, dollar_boot_subdirs));
+        RET_GATHER(r, remove_entry_directory(&c, j, c.esp_fd));
 
         if (c.xbootldr_fd >= 0) {
                 /* Remove a subset of these also from the XBOOTLDR partition if it exists */
@@ -2066,6 +2020,7 @@ int vl_method_install(
                         /* path= */ NULL,
                         /* unprivileged_mode= */ false,
                         &p.context.esp_path,
+                        &p.context.esp_fd,
                         &p.context.esp_part,
                         &p.context.esp_pstart,
                         &p.context.esp_psize,
@@ -2080,7 +2035,8 @@ int vl_method_install(
                         p.context.root_fd,
                         /* path= */ NULL,
                         /* unprivileged_mode= */ false,
-                        &p.context.xbootldr_path);
+                        &p.context.xbootldr_path,
+                        &p.context.xbootldr_fd);
         if (r == -ENOKEY)
                 log_debug_errno(r, "Didn't find an XBOOTLDR partition, using ESP as $BOOT.");
         else if (r < 0)
index 2ef491c54f84e6daef4cc33e034a10536a65396d..be33d9f950fbf7eb6a2790e5293bb99c2a0a7ceb 100644 (file)
@@ -111,8 +111,8 @@ static int set_system_token(void) {
         return 0;
 }
 
-int install_random_seed(const char *esp) {
-        _cleanup_close_ int esp_fd = -EBADF, loader_dir_fd = -EBADF, fd = -EBADF;
+int install_random_seed(const char *esp, int esp_fd) {
+        _cleanup_close_ int loader_dir_fd = -EBADF, fd = -EBADF;
         _cleanup_free_ char *tmp = NULL;
         uint8_t buffer[RANDOM_EFI_SEED_SIZE];
         struct sha256_ctx hash_state;
@@ -120,16 +120,13 @@ int install_random_seed(const char *esp) {
         int r;
 
         assert(esp);
+        assert(esp_fd >= 0);
 
         assert_cc(RANDOM_EFI_SEED_SIZE == SHA256_DIGEST_SIZE);
 
         if (!arg_install_random_seed)
                 return 0;
 
-        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);
-
         (void) random_seed_verify_permissions(esp_fd, S_IFDIR);
 
         loader_dir_fd = open_mkdir_at(esp_fd, "loader", O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOFOLLOW, 0775);
@@ -204,7 +201,8 @@ int install_random_seed(const char *esp) {
 int verb_random_seed(int argc, char *argv[], uintptr_t _data, void *userdata) {
         int r;
 
-        r = find_esp_and_warn(arg_root, arg_esp_path, /* unprivileged_mode= */ false, &arg_esp_path);
+        _cleanup_close_ int esp_fd = -EBADF;
+        r = find_esp_and_warn(arg_root, arg_esp_path, /* unprivileged_mode= */ false, &arg_esp_path, &esp_fd);
         if (r == -ENOKEY) {
                 /* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
                 if (arg_graceful() == ARG_GRACEFUL_NO)
@@ -216,7 +214,7 @@ int verb_random_seed(int argc, char *argv[], uintptr_t _data, void *userdata) {
         if (r < 0)
                 return r;
 
-        r = install_random_seed(arg_esp_path);
+        r = install_random_seed(arg_esp_path, esp_fd);
         if (r < 0)
                 return r;
 
index 722c511b748086b0481f42ed9fa9e2b25fe14816..1764668b3a3d54412dd956319682d4dbb6114067 100644 (file)
@@ -3,6 +3,6 @@
 
 #include "shared-forward.h"
 
-int install_random_seed(const char *esp);
+int install_random_seed(const char *esp, int esp_fd);
 
 int verb_random_seed(int argc, char *argv[], uintptr_t _data, void *userdata);
index 76e62847f36eb3f9c7f52d581af639b376c66110..2c0eb4d1d00d485c3c09882ea2efd19e777852e9 100644 (file)
@@ -334,6 +334,7 @@ int verb_status(int argc, char *argv[], uintptr_t _data, void *userdata) {
 
         r = acquire_esp(/* unprivileged_mode= */ -1,
                         /* graceful= */ false,
+                        /* ret_fd= */ NULL,
                         /* ret_part= */ NULL,
                         /* ret_pstart= */ NULL,
                         /* ret_psize= */ NULL,
@@ -352,6 +353,7 @@ int verb_status(int argc, char *argv[], uintptr_t _data, void *userdata) {
 
         r = acquire_xbootldr(
                         /* unprivileged_mode= */ -1,
+                        /* ret_fd= */ NULL,
                         &xbootldr_uuid,
                         &xbootldr_devid);
         if (arg_print_dollar_boot_path) {
@@ -644,13 +646,24 @@ int verb_list(int argc, char *argv[], uintptr_t _data, void *userdata) {
 
         (void) touch_variables();
 
-        r = acquire_esp(/* unprivileged_mode= */ -1, /* graceful= */ false, NULL, NULL, NULL, NULL, &esp_devid);
+        r = acquire_esp(/* unprivileged_mode= */ -1,
+                        /* graceful= */ false,
+                        /* ret_fd= */ NULL,
+                        /* ret_part= */ NULL,
+                        /* ret_pstart= */ NULL,
+                        /* ret_psize= */ NULL,
+                        /* ret_uuid= */ NULL,
+                        &esp_devid);
         if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */
                 return log_error_errno(r, "Failed to determine ESP location: %m");
         if (r < 0)
                 return r;
 
-        r = acquire_xbootldr(/* unprivileged_mode= */ -1, NULL, &xbootldr_devid);
+        r = acquire_xbootldr(
+                        /* unprivileged_mode= */ -1,
+                        /* ret_fd= */ NULL,
+                        /* ret_uuid= */ NULL,
+                        &xbootldr_devid);
         if (r == -EACCES)
                 return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
         if (r < 0)
@@ -683,6 +696,7 @@ int vl_method_list_boot_entries(sd_varlink *link, sd_json_variant *parameters, s
 
         r = acquire_esp(/* unprivileged_mode= */ false,
                         /* graceful= */ false,
+                        /* ret_fd= */ NULL,
                         /* ret_part= */ NULL,
                         /* ret_pstart= */ NULL,
                         /* ret_psize= */ NULL,
@@ -695,6 +709,7 @@ int vl_method_list_boot_entries(sd_varlink *link, sd_json_variant *parameters, s
 
         r = acquire_xbootldr(
                         /* unprivileged_mode= */ false,
+                        /* ret_fd= */ NULL,
                         /* ret_uuid= */ NULL,
                         &xbootldr_devid);
         if (r == -EACCES)
index b5cc8397989734f130cc4772a0d8805f7907ecf2..0d0e7ad076b602aafc828662bd0f3a3f6422d454 100644 (file)
@@ -205,6 +205,7 @@ int verb_unlink(int argc, char *argv[], uintptr_t _data, void *userdata) {
 
         r = acquire_esp(/* unprivileged_mode= */ false,
                         /* graceful= */ false,
+                        /* ret_fd= */ NULL,
                         /* ret_part= */ NULL,
                         /* ret_pstart= */ NULL,
                         /* ret_psize= */ NULL,
@@ -217,6 +218,7 @@ int verb_unlink(int argc, char *argv[], uintptr_t _data, void *userdata) {
 
         r = acquire_xbootldr(
                         /* unprivileged_mode= */ false,
+                        /* ret_fd= */ NULL,
                         /* ret_uuid= */ NULL,
                         &xbootldr_devid);
         if (r == -EACCES)
index ef1116ced72bfaea4eee08f86ebb200c4d2936f6..239a0c9273073aab1e642b725e10380519d53174 100644 (file)
@@ -21,6 +21,7 @@
 #include "efi-loader.h"
 #include "efivars.h"
 #include "escape.h"
+#include "fd-util.h"
 #include "find-esp.h"
 #include "format-table.h"
 #include "image-policy.h"
@@ -100,16 +101,16 @@ static const char* const install_source_table[_INSTALL_SOURCE_MAX] = {
 
 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(install_source, InstallSource);
 
-int acquire_esp(
-                int unprivileged_mode,
+int acquire_esp(int unprivileged_mode,
                 bool graceful,
+                int *ret_fd,
                 uint32_t *ret_part,
                 uint64_t *ret_pstart,
                 uint64_t *ret_psize,
                 sd_id128_t *ret_uuid,
                 dev_t *ret_devid) {
 
-        char *np;
+        _cleanup_free_ char *np = NULL;
         int r;
 
         /* Find the ESP, and log about errors. Note that find_esp_and_warn() will log in all error cases on
@@ -118,7 +119,7 @@ int acquire_esp(
          * we simply eat up the error here, so that --list and --status work too, without noise about
          * this). */
 
-        r = find_esp_and_warn_full(arg_root, arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid);
+        r = find_esp_and_warn_full(arg_root, arg_esp_path, unprivileged_mode, &np, ret_fd, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid);
         if (r == -ENOKEY) {
                 if (graceful)
                         return log_full_errno(arg_quiet ? LOG_DEBUG : LOG_INFO, r,
@@ -134,27 +135,44 @@ int acquire_esp(
         free_and_replace(arg_esp_path, np);
         log_debug("Using EFI System Partition at %s.", arg_esp_path);
 
-        return 0;
+        return 1; /* for symmetry with acquire_xbootldr() below: found */
 }
 
 int acquire_xbootldr(
                 int unprivileged_mode,
+                int *ret_fd,
                 sd_id128_t *ret_uuid,
                 dev_t *ret_devid) {
 
-        char *np;
         int r;
 
-        r = find_xbootldr_and_warn_full(arg_root, arg_xbootldr_path, unprivileged_mode, &np, ret_uuid, ret_devid);
-        if (r == -ENOKEY || path_equal(np, arg_esp_path)) {
-                log_debug("Didn't find an XBOOTLDR partition, using the ESP as $BOOT.");
+        _cleanup_free_ char *np = NULL;
+        _cleanup_close_ int fd = -EBADF;
+        r = find_xbootldr_and_warn_full(
+                        arg_root,
+                        arg_xbootldr_path,
+                        unprivileged_mode,
+                        &np,
+                        ret_fd ? &fd : NULL,
+                        ret_uuid,
+                        ret_devid);
+        if (r == -ENOKEY || (r >= 0 && arg_esp_path && path_equal(np, arg_esp_path))) {
+
+                if (arg_esp_path)
+                        log_debug("Didn't find an XBOOTLDR partition, using the ESP as $BOOT.");
+                else
+                        log_debug("Found neither an XBOOTLDR partition, nor an ESP.");
+
                 arg_xbootldr_path = mfree(arg_xbootldr_path);
 
+                if (ret_fd)
+                        *ret_fd = -EBADF;
                 if (ret_uuid)
                         *ret_uuid = SD_ID128_NULL;
                 if (ret_devid)
                         *ret_devid = 0;
-                return 0;
+
+                return 0; /* not found */
         }
         if (r < 0)
                 return r;
@@ -162,7 +180,10 @@ int acquire_xbootldr(
         free_and_replace(arg_xbootldr_path, np);
         log_debug("Using XBOOTLDR partition at %s as $BOOT.", arg_xbootldr_path);
 
-        return 1;
+        if (ret_fd)
+                *ret_fd = TAKE_FD(fd);
+
+        return 1; /* found */
 }
 
 static int print_loader_or_stub_path(void) {
@@ -199,9 +220,14 @@ static int print_loader_or_stub_path(void) {
         }
 
         sd_id128_t esp_uuid;
-        r = acquire_esp(/* unprivileged_mode= */ false, /* graceful= */ false,
-                        /* ret_part= */ NULL, /* ret_pstart= */ NULL, /* ret_psize= */ NULL,
-                        &esp_uuid, /* ret_devid= */ NULL);
+        r = acquire_esp(/* unprivileged_mode= */ false,
+                        /* graceful= */ false,
+                        /* ret_fd= */ NULL,
+                        /* ret_part= */ NULL,
+                        /* ret_pstart= */ NULL,
+                        /* ret_psize= */ NULL,
+                        &esp_uuid,
+                        /* ret_devid= */ NULL);
         if (r < 0)
                 return r;
 
@@ -211,7 +237,10 @@ static int print_loader_or_stub_path(void) {
         else if (arg_print_stub_path) { /* In case of the stub, also look for things in the xbootldr partition */
                 sd_id128_t xbootldr_uuid;
 
-                r = acquire_xbootldr(/* unprivileged_mode= */ false, &xbootldr_uuid, /* ret_devid= */ NULL);
+                r = acquire_xbootldr(/* unprivileged_mode= */ false,
+                                     /* ret_fd= */ NULL,
+                                     &xbootldr_uuid,
+                                     /* ret_devid= */ NULL);
                 if (r < 0)
                         return r;
 
index 07e98f8559491b7b95b2e8a97c3ebe2a37a18288..d3d6583c0241da15940bc1d716994c66388ebaac 100644 (file)
@@ -58,8 +58,8 @@ static inline const char* arg_dollar_boot_path(void) {
 
 GracefulMode arg_graceful(void);
 
-int acquire_esp(int unprivileged_mode, bool graceful, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid);
-int acquire_xbootldr(int unprivileged_mode, sd_id128_t *ret_uuid, dev_t *ret_devid);
+int acquire_esp(int unprivileged_mode, bool graceful, int *ret_fd, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid);
+int acquire_xbootldr(int unprivileged_mode, int *ret_fd, sd_id128_t *ret_uuid, dev_t *ret_devid);
 
 /* EFI_BOOT_OPTION_DESCRIPTION_MAX sets the maximum length for the boot option description
  * stored in NVRAM. The UEFI spec does not specify a minimum or maximum length for this
index 8c0abba4207ada04a0124d919268e4db3c2e1ed7..aeded46c22d9fe483337226f4763e4234db7e63c 100644 (file)
@@ -570,7 +570,8 @@ static int context_acquire_xbootldr(Context *c) {
                         /* rfd= */ c->rfd,
                         /* path= */ arg_xbootldr_path,
                         /* unprivileged_mode= */ -1,
-                        /* ret_path= */ &c->boot_root);
+                        /* ret_path= */ &c->boot_root,
+                        /* ret_fd= */ NULL);
         if (r == -ENOKEY) {
                 log_debug_errno(r, "Couldn't find an XBOOTLDR partition.");
                 return 0;
@@ -594,7 +595,8 @@ static int context_acquire_esp(Context *c) {
                         /* rfd= */ c->rfd,
                         /* path= */ arg_esp_path,
                         /* unprivileged_mode= */ -1,
-                        /* ret_path= */ &c->boot_root);
+                        /* ret_path= */ &c->boot_root,
+                        /* ret_fd= */ NULL);
         if (r == -ENOKEY) {
                 log_debug_errno(r, "Couldn't find EFI system partition, ignoring.");
                 return 0;
index 2d9906acb9b878e56e5fdde4998b1ef2a8e69c4e..c3774a5235fad0dd26450d66ccb953baf22a5ea2 100644 (file)
@@ -1597,6 +1597,7 @@ int boot_config_load_auto(
                         override_esp_path,
                         /* unprivileged_mode= */ false,
                         &esp_where,
+                        /* ret_fd= */ NULL,
                         /* ret_part= */ NULL,
                         /* ret_pstart= */ NULL,
                         /* ret_psize= */ NULL,
@@ -1610,6 +1611,7 @@ int boot_config_load_auto(
                         override_xbootldr_path,
                         /* unprivileged_mode= */ false,
                         &xbootldr_where,
+                        /* ret_fd= */ NULL,
                         /* ret_uuid= */ NULL,
                         &xbootldr_devid);
         if (r < 0 && r != -ENOKEY)
index 3ff214a09a36145bc4aa3574b99b75278f74c286..d3383aebb6faf074266a6e66f7a9e91d949d78f2 100644 (file)
@@ -1709,7 +1709,8 @@ int get_global_boot_credentials_path(char **ret) {
                         /* root= */ NULL,
                         /* path= */ NULL,
                         /* unprivileged_mode= */ false,
-                        &path);
+                        &path,
+                        /* ret_fd= */ NULL);
         if (r < 0) {
                 if (r != -ENOKEY)
                         return log_error_errno(r, "Failed to find XBOOTLDR partition: %m");
@@ -1718,7 +1719,8 @@ int get_global_boot_credentials_path(char **ret) {
                                 /* root= */ NULL,
                                 /* path= */ NULL,
                                 /* unprivileged_mode= */ false,
-                                &path);
+                                &path,
+                                /* ret_fd= */ NULL);
                 if (r < 0) {
                         if (r != -ENOKEY)
                                 return log_error_errno(r, "Failed to find ESP partition: %m");
index 1d13683f1286e97abeb5d7133c469c5f5377dc21..d29719785feddf8af800d95bba350bd6c935e6aa 100644 (file)
@@ -19,7 +19,6 @@
 #include "errno-util.h"
 #include "fd-util.h"
 #include "find-esp.h"
-#include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "stat-util.h"
@@ -260,33 +259,24 @@ static int verify_esp_udev(
 }
 
 static int verify_fsroot_dir(
-                int dir_fd,
                 const char *path,
+                int fd,
                 VerifyESPFlags flags,
                 dev_t *ret_dev) {
 
         bool searching = FLAGS_SET(flags, VERIFY_ESP_SEARCHING),
                 unprivileged_mode = FLAGS_SET(flags, VERIFY_ESP_UNPRIVILEGED_MODE);
-        _cleanup_free_ char *f = NULL;
-        struct statx sx;
         int r;
 
         /* Checks if the specified directory is at the root of its file system, and returns device
          * major/minor of the device, if it is. */
 
-        assert(dir_fd >= 0);
         assert(path);
+        assert(fd >= 0);
 
-        /* We pass the full path from the root directory file descriptor so we can use it for logging, but
-         * dir_fd points to the parent directory of the final component of the given path, so we extract the
-         * filename and operate on that. */
-
-        r = path_extract_filename(path, &f);
-        if (r < 0 && r != -EADDRNOTAVAIL)
-                return log_error_errno(r, "Failed to extract filename of \"%s\": %m", path);
-
-        r = xstatx_full(dir_fd, f,
-                        AT_SYMLINK_NOFOLLOW,
+        struct statx sx;
+        r = xstatx_full(fd, /* path= */ NULL,
+                        /* statx_flags= */ 0,
                         /* xstatx_flags= */ 0,
                         STATX_TYPE|STATX_INO,
                         /* optional_mask = */ 0,
@@ -310,7 +300,7 @@ static int verify_fsroot_dir(
                 return 0;
 
         if (sx.stx_dev_major == 0) /* Hmm, maybe a btrfs device, and the caller asked for the backing device? Then let's try to get it. */
-                return btrfs_get_block_device_at(dir_fd, strempty(f), ret_dev);
+                return btrfs_get_block_device_fd(fd, ret_dev);
 
         *ret_dev = makedev(sx.stx_dev_major, sx.stx_dev_minor);
         return 0;
@@ -320,6 +310,7 @@ static int verify_esp(
                 int rfd,
                 const char *path,
                 char **ret_path,
+                int *ret_fd,
                 uint32_t *ret_part,
                 uint64_t *ret_pstart,
                 uint64_t *ret_psize,
@@ -329,9 +320,6 @@ static int verify_esp(
 
         bool searching = FLAGS_SET(flags, VERIFY_ESP_SEARCHING),
                 unprivileged_mode = FLAGS_SET(flags, VERIFY_ESP_UNPRIVILEGED_MODE);
-        _cleanup_free_ char *p = NULL;
-        _cleanup_close_ int pfd = -EBADF;
-        dev_t devid = 0;
         int r;
 
         assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
@@ -347,87 +335,71 @@ static int verify_esp(
         /* Non-root user can only check the status, so if an error occurred in the following, it does not cause any
          * issues. Let's also, silence the error messages. */
 
-        r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT|CHASE_TRIGGER_AUTOFS, &p, &pfd);
+        _cleanup_free_ char *p = NULL;
+        _cleanup_close_ int fd = -EBADF;
+        r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_TRIGGER_AUTOFS, &p, &fd);
         if (r < 0)
                 return log_full_errno((searching && r == -ENOENT) ||
                                       (unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR,
-                                      r, "Failed to open parent directory of \"%s\": %m", path);
+                                      r, "Failed to open directory \"%s\": %m", path);
 
         if (!FLAGS_SET(flags, VERIFY_ESP_SKIP_FSTYPE_CHECK)) {
-                _cleanup_free_ char *f = NULL;
-                struct statfs sfs;
-
-                r = path_extract_filename(p, &f);
-                if (r < 0 && r != -EADDRNOTAVAIL)
-                        return log_error_errno(r, "Failed to extract filename of \"%s\": %m", p);
 
-                /* Trigger any automounts so that xstatfsat() operates on the mount instead of the mountpoint
-                 * directory. */
-                r = trigger_automount_at(pfd, f);
+                r = fd_is_fs_type(fd, MSDOS_SUPER_MAGIC);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to trigger automount at \"%s\": %m", p);
-
-                r = xstatfsat(pfd, strempty(f), &sfs);
-                if (r < 0)
-                        /* If we are searching for the mount point, don't generate a log message if we can't find the path */
-                        return log_full_errno((searching && r == -ENOENT) ||
-                                              (unprivileged_mode && r == -EACCES) ? LOG_DEBUG : LOG_ERR, r,
+                        return log_full_errno((unprivileged_mode && r == -EACCES) ? LOG_DEBUG : LOG_ERR, r,
                                               "Failed to check file system type of \"%s\": %m", p);
-
-                if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC))
+                if (!r)
                         return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
                                               SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
                                               "File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p);
         }
 
-        r = verify_fsroot_dir(pfd, p, flags, FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK) ? NULL : &devid);
+        dev_t devid = 0;
+        r = verify_fsroot_dir(p, fd, flags, FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK) ? NULL : &devid);
         if (r < 0)
                 return r;
 
         /* In a container we don't have access to block devices, skip this part of the verification, we trust
          * the container manager set everything up correctly on its own. */
-        if (FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK))
-                goto finish;
+        if (FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK)) {
 
-        if (devnum_is_zero(devid))
-                return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
-                                      SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
-                                      "Could not determine backing block device of directory \"%s\" (btrfs RAID?).", p);
+                if (ret_part)
+                        *ret_part = 0;
+                if (ret_pstart)
+                        *ret_pstart = 0;
+                if (ret_psize)
+                        *ret_psize = 0;
+                if (ret_uuid)
+                        *ret_uuid = SD_ID128_NULL;
 
-        /* If we are unprivileged we ask udev for the metadata about the partition. If we are privileged we
-         * use blkid instead. Why? Because this code is called from 'bootctl' which is pretty much an
-         * emergency recovery tool that should also work when udev isn't up (i.e. from the emergency shell),
-         * however blkid can't work if we have no privileges to access block devices directly, which is why
-         * we use udev in that case. */
-        if (unprivileged_mode)
-                r = verify_esp_udev(devid, flags, ret_part, ret_pstart, ret_psize, ret_uuid);
-        else
-                r = verify_esp_blkid(devid, flags, ret_part, ret_pstart, ret_psize, ret_uuid);
-        if (r < 0)
-                return r;
+        } else {
+                if (devnum_is_zero(devid))
+                        return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
+                                              SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+                                              "Could not determine backing block device of directory \"%s\" (btrfs RAID?).", p);
+
+                /* If we are unprivileged we ask udev for the metadata about the partition. If we are privileged we
+                 * use blkid instead. Why? Because this code is called from 'bootctl' which is pretty much an
+                 * emergency recovery tool that should also work when udev isn't up (i.e. from the emergency shell),
+                 * however blkid can't work if we have no privileges to access block devices directly, which is why
+                 * we use udev in that case. */
+                if (unprivileged_mode)
+                        r = verify_esp_udev(devid, flags, ret_part, ret_pstart, ret_psize, ret_uuid);
+                else
+                        r = verify_esp_blkid(devid, flags, ret_part, ret_pstart, ret_psize, ret_uuid);
+                if (r < 0)
+                        return r;
+        }
 
         if (ret_path)
                 *ret_path = TAKE_PTR(p);
+        if (ret_fd)
+                *ret_fd = TAKE_FD(fd);
         if (ret_devid)
                 *ret_devid = devid;
 
         return 0;
-
-finish:
-        if (ret_path)
-                *ret_path = TAKE_PTR(p);
-        if (ret_part)
-                *ret_part = 0;
-        if (ret_pstart)
-                *ret_pstart = 0;
-        if (ret_psize)
-                *ret_psize = 0;
-        if (ret_uuid)
-                *ret_uuid = SD_ID128_NULL;
-        if (ret_devid)
-                *ret_devid = 0;
-
-        return 0;
 }
 
 int find_esp_and_warn_at_full(
@@ -435,6 +407,7 @@ int find_esp_and_warn_at_full(
                 const char *path,
                 int unprivileged_mode,
                 char **ret_path,
+                int *ret_fd,
                 uint32_t *ret_part,
                 uint64_t *ret_pstart,
                 uint64_t *ret_psize,
@@ -455,7 +428,7 @@ int find_esp_and_warn_at_full(
         flags = verify_esp_flags_init(unprivileged_mode, "SYSTEMD_RELAX_ESP_CHECKS");
 
         if (path)
-                return verify_esp(rfd, path, ret_path, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid, flags);
+                return verify_esp(rfd, path, ret_path, ret_fd, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid, flags);
 
         path = getenv("SYSTEMD_ESP_PATH");
         if (path) {
@@ -484,6 +457,8 @@ int find_esp_and_warn_at_full(
 
                 if (ret_path)
                         *ret_path = TAKE_PTR(p);
+                if (ret_fd)
+                        *ret_fd = TAKE_FD(fd);
                 if (ret_part)
                         *ret_part = 0;
                 if (ret_pstart)
@@ -499,7 +474,15 @@ int find_esp_and_warn_at_full(
         }
 
         FOREACH_STRING(dir, "/efi", "/boot", "/boot/efi") {
-                r = verify_esp(rfd, dir, ret_path, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid,
+                r = verify_esp(rfd,
+                               dir,
+                               ret_path,
+                               ret_fd,
+                               ret_part,
+                               ret_pstart,
+                               ret_psize,
+                               ret_uuid,
+                               ret_devid,
                                flags | VERIFY_ESP_SEARCHING);
                 if (r >= 0)
                         return 0;
@@ -516,20 +499,16 @@ int find_esp_and_warn_full(
                 const char *path,
                 int unprivileged_mode,
                 char **ret_path,
+                int *ret_fd,
                 uint32_t *ret_part,
                 uint64_t *ret_pstart,
                 uint64_t *ret_psize,
                 sd_id128_t *ret_uuid,
                 dev_t *ret_devid) {
 
-        _cleanup_close_ int rfd = -EBADF;
-        _cleanup_free_ char *p = NULL;
-        uint32_t part;
-        uint64_t pstart, psize;
-        sd_id128_t uuid;
-        dev_t devid;
         int r;
 
+        _cleanup_close_ int rfd = -EBADF;
         if (empty_or_root(root))
                 rfd = XAT_FDROOT;
         else {
@@ -538,11 +517,18 @@ int find_esp_and_warn_full(
                         return -errno;
         }
 
+        _cleanup_close_ int fd = -EBADF;
+        _cleanup_free_ char *p = NULL;
+        uint32_t part;
+        uint64_t pstart, psize;
+        sd_id128_t uuid;
+        dev_t devid;
         r = find_esp_and_warn_at_full(
                         rfd,
                         path,
                         unprivileged_mode,
                         ret_path ? &p : NULL,
+                        ret_fd ? &fd : NULL,
                         ret_part ? &part : NULL,
                         ret_pstart ? &pstart : NULL,
                         ret_psize ? &psize : NULL,
@@ -556,6 +542,8 @@ int find_esp_and_warn_full(
                 if (r < 0)
                         return r;
         }
+        if (ret_fd)
+                *ret_fd = TAKE_FD(fd);
         if (ret_part)
                 *ret_part = part;
         if (ret_pstart)
@@ -734,64 +722,59 @@ static int verify_xbootldr(
                 const char *path,
                 VerifyESPFlags flags,
                 char **ret_path,
+                int *ret_fd,
                 sd_id128_t *ret_uuid,
                 dev_t *ret_devid) {
 
-        _cleanup_free_ char *p = NULL;
-        _cleanup_close_ int pfd = -EBADF;
         bool searching = FLAGS_SET(flags, VERIFY_ESP_SEARCHING),
                 unprivileged_mode = FLAGS_SET(flags, VERIFY_ESP_UNPRIVILEGED_MODE);
-        dev_t devid = 0;
         int r;
 
         assert(rfd >= 0 || IN_SET(rfd, AT_FDCWD, XAT_FDROOT));
         assert(path);
 
-        r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT|CHASE_TRIGGER_AUTOFS, &p, &pfd);
+        _cleanup_free_ char *p = NULL;
+        _cleanup_close_ int fd = -EBADF;
+        r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_TRIGGER_AUTOFS, &p, &fd);
         if (r < 0)
                 return log_full_errno((searching && r == -ENOENT) ||
                                       (unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR,
-                                      r, "Failed to open parent directory of \"%s\": %m", path);
+                                      r, "Failed to open directory \"%s\": %m", path);
 
-        r = verify_fsroot_dir(pfd, p, flags, FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK) ? NULL : &devid);
+        dev_t devid = 0;
+        r = verify_fsroot_dir(p, fd, flags, FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK) ? NULL : &devid);
         if (r < 0)
                 return r;
 
-        if (FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK))
-                goto finish;
-
-        if (devnum_is_zero(devid))
-                return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
-                                      SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
-                                      "Could not determine backing block device of directory \"%s\" (btrfs RAID?).%s",
-                                      p,
-                                      searching ? "" :
-                                      "\nHint: set $SYSTEMD_RELAX_XBOOTLDR_CHECKS=yes environment variable "
-                                      "to bypass this and further verifications for the directory.");
-
-        if (unprivileged_mode)
-                r = verify_xbootldr_udev(devid, flags, ret_uuid);
-        else
-                r = verify_xbootldr_blkid(devid, flags, ret_uuid);
-        if (r < 0)
-                return r;
+        if (FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK)) {
+                if (ret_uuid)
+                        *ret_uuid = SD_ID128_NULL;
+        } else {
+                if (devnum_is_zero(devid))
+                        return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
+                                              SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+                                              "Could not determine backing block device of directory \"%s\" (btrfs RAID?).%s",
+                                              p,
+                                              searching ? "" :
+                                              "\nHint: set $SYSTEMD_RELAX_XBOOTLDR_CHECKS=yes environment variable "
+                                              "to bypass this and further verifications for the directory.");
+
+                if (unprivileged_mode)
+                        r = verify_xbootldr_udev(devid, flags, ret_uuid);
+                else
+                        r = verify_xbootldr_blkid(devid, flags, ret_uuid);
+                if (r < 0)
+                        return r;
+        }
 
         if (ret_path)
                 *ret_path = TAKE_PTR(p);
+        if (ret_fd)
+                *ret_fd = TAKE_FD(fd);
         if (ret_devid)
                 *ret_devid = devid;
 
         return 0;
-
-finish:
-        if (ret_path)
-                *ret_path = TAKE_PTR(p);
-        if (ret_uuid)
-                *ret_uuid = SD_ID128_NULL;
-        if (ret_devid)
-                *ret_devid = 0;
-
-        return 0;
 }
 
 int find_xbootldr_and_warn_at_full(
@@ -799,6 +782,7 @@ int find_xbootldr_and_warn_at_full(
                 const char *path,
                 int unprivileged_mode,
                 char **ret_path,
+                int *ret_fd,
                 sd_id128_t *ret_uuid,
                 dev_t *ret_devid) {
 
@@ -812,7 +796,7 @@ int find_xbootldr_and_warn_at_full(
         flags = verify_esp_flags_init(unprivileged_mode, "SYSTEMD_RELAX_XBOOTLDR_CHECKS");
 
         if (path)
-                return verify_xbootldr(rfd, path, flags, ret_path, ret_uuid, ret_devid);
+                return verify_xbootldr(rfd, path, flags, ret_path, ret_fd, ret_uuid, ret_devid);
 
         path = getenv("SYSTEMD_XBOOTLDR_PATH");
         if (path) {
@@ -837,6 +821,8 @@ int find_xbootldr_and_warn_at_full(
 
                 if (ret_path)
                         *ret_path = TAKE_PTR(p);
+                if (ret_fd)
+                        *ret_fd = TAKE_FD(fd);
                 if (ret_uuid)
                         *ret_uuid = SD_ID128_NULL;
                 if (ret_devid)
@@ -845,7 +831,14 @@ int find_xbootldr_and_warn_at_full(
                 return 0;
         }
 
-        r = verify_xbootldr(rfd, "/boot", flags | VERIFY_ESP_SEARCHING, ret_path, ret_uuid, ret_devid);
+        r = verify_xbootldr(
+                        rfd,
+                        "/boot",
+                        flags | VERIFY_ESP_SEARCHING,
+                        ret_path,
+                        ret_fd,
+                        ret_uuid,
+                        ret_devid);
         if (r < 0) {
                 if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL, -ENOTDIR, -ENOTTY)) /* This one is not it */
                         return r;
@@ -861,15 +854,13 @@ int find_xbootldr_and_warn_full(
                 const char *path,
                 int unprivileged_mode,
                 char **ret_path,
+                int *ret_fd,
                 sd_id128_t *ret_uuid,
                 dev_t *ret_devid) {
 
-        _cleanup_close_ int rfd = -EBADF;
-        _cleanup_free_ char *p = NULL;
-        sd_id128_t uuid;
-        dev_t devid;
         int r;
 
+        _cleanup_close_ int rfd = -EBADF;
         if (empty_or_root(root))
                 rfd = XAT_FDROOT;
         else {
@@ -878,11 +869,16 @@ int find_xbootldr_and_warn_full(
                         return -errno;
         }
 
+        _cleanup_close_ int fd = -EBADF;
+        _cleanup_free_ char *p = NULL;
+        sd_id128_t uuid;
+        dev_t devid;
         r = find_xbootldr_and_warn_at_full(
                         rfd,
                         path,
                         unprivileged_mode,
                         ret_path ? &p : NULL,
+                        ret_fd ? &fd : NULL,
                         ret_uuid ? &uuid : NULL,
                         ret_devid ? &devid : NULL);
         if (r < 0)
@@ -893,6 +889,8 @@ int find_xbootldr_and_warn_full(
                 if (r < 0)
                         return r;
         }
+        if (ret_fd)
+                *ret_fd = TAKE_FD(fd);
         if (ret_uuid)
                 *ret_uuid = uuid;
         if (ret_devid)
index 30b7c4a76117ef4bef6d7a6b94bfb7dcafb58145..ad02bcd8f3f60ec5c57c03f942c44af5a3b7a66b 100644 (file)
@@ -4,22 +4,22 @@
 
 #include "shared-forward.h"
 
-int find_esp_and_warn_at_full(int rfd, const char *path, int unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid);
-int find_esp_and_warn_full(const char *root, const char *path, int unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid);
+int find_esp_and_warn_at_full(int rfd, const char *path, int unprivileged_mode, char **ret_path, int *ret_fd, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid);
+int find_esp_and_warn_full(const char *root, const char *path, int unprivileged_mode, char **ret_path, int *ret_fd, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid);
 
-static inline int find_esp_and_warn_at(int rfd, const char *path, int unprivileged_mode, char **ret_path) {
-        return find_esp_and_warn_at_full(rfd, path, unprivileged_mode, ret_path, NULL, NULL, NULL, NULL, NULL);
+static inline int find_esp_and_warn_at(int rfd, const char *path, int unprivileged_mode, char **ret_path, int *ret_fd) {
+        return find_esp_and_warn_at_full(rfd, path, unprivileged_mode, ret_path, ret_fd, NULL, NULL, NULL, NULL, NULL);
 }
-static inline int find_esp_and_warn(const char *root, const char *path, int unprivileged_mode, char **ret_path) {
-        return find_esp_and_warn_full(root, path, unprivileged_mode, ret_path, NULL, NULL, NULL, NULL, NULL);
+static inline int find_esp_and_warn(const char *root, const char *path, int unprivileged_mode, char **ret_path, int *ret_fd) {
+        return find_esp_and_warn_full(root, path, unprivileged_mode, ret_path, ret_fd, NULL, NULL, NULL, NULL, NULL);
 }
 
-int find_xbootldr_and_warn_at_full(int rfd, const char *path, int unprivileged_mode, char **ret_path, sd_id128_t *ret_uuid, dev_t *ret_devid);
-int find_xbootldr_and_warn_full(const char *root, const char *path, int unprivileged_mode, char **ret_path, sd_id128_t *ret_uuid, dev_t *ret_devid);
+int find_xbootldr_and_warn_at_full(int rfd, const char *path, int unprivileged_mode, char **ret_path, int *ret_fd, sd_id128_t *ret_uuid, dev_t *ret_devid);
+int find_xbootldr_and_warn_full(const char *root, const char *path, int unprivileged_mode, char **ret_path, int *ret_fd, sd_id128_t *ret_uuid, dev_t *ret_devid);
 
-static inline int find_xbootldr_and_warn_at(int rfd, const char *path, int unprivileged_mode, char **ret_path) {
-        return find_xbootldr_and_warn_at_full(rfd, path, unprivileged_mode, ret_path, NULL, NULL);
+static inline int find_xbootldr_and_warn_at(int rfd, const char *path, int unprivileged_mode, char **ret_path, int *ret_fd) {
+        return find_xbootldr_and_warn_at_full(rfd, path, unprivileged_mode, ret_path, ret_fd, NULL, NULL);
 }
-static inline int find_xbootldr_and_warn(const char *root, const char *path, int unprivileged_mode, char **ret_path) {
-        return find_xbootldr_and_warn_full(root, path, unprivileged_mode, ret_path, NULL, NULL);
+static inline int find_xbootldr_and_warn(const char *root, const char *path, int unprivileged_mode, char **ret_path, int *ret_fd) {
+        return find_xbootldr_and_warn_full(root, path, unprivileged_mode, ret_path, ret_fd, NULL, NULL);
 }
index b819fcd5b8586871c71bb179785ef92f882ff588..5865a39e2f1f9890b59ca186e9327ce96586c115 100644 (file)
@@ -839,9 +839,9 @@ int resource_resolve_path(
                 } else { /* boot, esp, or xbootldr */
                         r = 0;
                         if (IN_SET(rr->path_relative_to, PATH_RELATIVE_TO_BOOT, PATH_RELATIVE_TO_XBOOTLDR))
-                                r = find_xbootldr_and_warn(root, /* path= */ NULL, /* unprivileged_mode= */ -1, &relative_to);
+                                r = find_xbootldr_and_warn(root, /* path= */ NULL, /* unprivileged_mode= */ -1, &relative_to, /* ret_fd= */ NULL);
                         if (r == -ENOKEY || rr->path_relative_to == PATH_RELATIVE_TO_ESP)
-                                r = find_esp_and_warn(root, /* path= */ NULL, /* unprivileged_mode= */ -1, &relative_to);
+                                r = find_esp_and_warn(root, /* path= */ NULL, /* unprivileged_mode= */ -1, &relative_to, /* ret_fd= */ NULL);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to resolve $BOOT: %m");
                         log_debug("Resolved $BOOT to '%s'", relative_to);
index 4ea6517157eecd1d9c8aaa4ed95aa4135786204b..71ad6b5e9d1c7f05b102a91e7688cbc61f7aff59 100644 (file)
@@ -147,32 +147,44 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return log_error_errno(r, "Failed to find 'swtpm' binary: %m");
 
-        _cleanup_free_ char *_esp = NULL;
-        const char *esp;
-        if (in_initrd())
+        _cleanup_free_ char *state_dir = NULL;
+        _cleanup_close_ int state_fd = -EBADF;
+        if (in_initrd()) {
                 /* The early ESP support uses only a single mount point, we do not need to search for it. */
-                esp = "/sysefi";
-        else {
+                r = chase("/loader/swtpm",
+                          "/sysefi",
+                          CHASE_PREFIX_ROOT|CHASE_TRIGGER_AUTOFS|CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY,
+                          &state_dir,
+                          &state_fd);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to open swtpm state directory in ESP: %m");
+        } else {
+                _cleanup_free_ char *esp_path = NULL;
+                _cleanup_close_ int esp_fd = -EBADF;
                 r = find_esp_and_warn(
                                 /* root= */ NULL,
                                 /* path= */ NULL,
                                 /* unprivileged_mode= */ false,
-                                &_esp);
+                                &esp_path,
+                                &esp_fd);
                 if (r == -ENOKEY) /* This one find_esp_and_warn() doesn't actually log about. */
                         return log_error_errno(r, "No ESP discovered.");
                 if (r < 0)
                         return r;
-                esp = _esp;
-        }
 
-        _cleanup_free_ char *state_dir = NULL;
-        _cleanup_close_ int state_fd = -EBADF;
-        r = chase("/loader/swtpm",
-                  esp, CHASE_PREFIX_ROOT|CHASE_TRIGGER_AUTOFS|CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY,
-                  &state_dir,
-                  &state_fd);
-        if (r < 0)
-                return log_error_errno(r, "Failed to open swtpm state directory in ESP: %m");
+                _cleanup_free_ char *unprefixed_state_dir = NULL;
+                r = chaseat(esp_fd,
+                            "/loader/swtpm",
+                            CHASE_TRIGGER_AUTOFS|CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY,
+                            &unprefixed_state_dir,
+                            &state_fd);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to open swtpm state directory in ESP: %m");
+
+                state_dir = path_join(esp_path, unprefixed_state_dir);
+                if (!state_dir)
+                        return log_oom();
+        }
 
         _cleanup_(unlink_and_freep) char *secret = NULL;
         r = prepare_secret(runtime_dir, &secret);