From 853d0649d584d78dde4dc40df711a4f0dc79e69e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 13 Apr 2026 18:04:29 +0200 Subject: [PATCH] find-esp: return pinned fd to ESP/XBOOTLDR 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. --- src/bless-boot/bless-boot.c | 2 + src/bootctl/bootctl-cleanup.c | 2 + src/bootctl/bootctl-install.c | 138 ++++++---------- src/bootctl/bootctl-random-seed.c | 14 +- src/bootctl/bootctl-random-seed.h | 2 +- src/bootctl/bootctl-status.c | 19 ++- src/bootctl/bootctl-unlink.c | 2 + src/bootctl/bootctl.c | 59 +++++-- src/bootctl/bootctl.h | 4 +- src/kernel-install/kernel-install.c | 6 +- src/shared/bootspec.c | 2 + src/shared/creds-util.c | 6 +- src/shared/find-esp.c | 240 ++++++++++++++-------------- src/shared/find-esp.h | 24 +-- src/sysupdate/sysupdate-resource.c | 4 +- src/tpm2-setup/tpm2-swtpm.c | 44 +++-- 16 files changed, 294 insertions(+), 274 deletions(-) diff --git a/src/bless-boot/bless-boot.c b/src/bless-boot/bless-boot.c index 86525f359a1..33fbdbb7608 100644 --- a/src/bless-boot/bless-boot.c +++ b/src/bless-boot/bless-boot.c @@ -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) diff --git a/src/bootctl/bootctl-cleanup.c b/src/bootctl/bootctl-cleanup.c index e654bca1049..1e8819bea18 100644 --- a/src/bootctl/bootctl-cleanup.c +++ b/src/bootctl/bootctl-cleanup.c @@ -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) diff --git a/src/bootctl/bootctl-install.c b/src/bootctl/bootctl-install.c index fc89ce143b9..96bc9213cf6 100644 --- a/src/bootctl/bootctl-install.c +++ b/src/bootctl/bootctl-install.c @@ -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) diff --git a/src/bootctl/bootctl-random-seed.c b/src/bootctl/bootctl-random-seed.c index 2ef491c54f8..be33d9f950f 100644 --- a/src/bootctl/bootctl-random-seed.c +++ b/src/bootctl/bootctl-random-seed.c @@ -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; diff --git a/src/bootctl/bootctl-random-seed.h b/src/bootctl/bootctl-random-seed.h index 722c511b748..1764668b3a3 100644 --- a/src/bootctl/bootctl-random-seed.h +++ b/src/bootctl/bootctl-random-seed.h @@ -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); diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c index 76e62847f36..2c0eb4d1d00 100644 --- a/src/bootctl/bootctl-status.c +++ b/src/bootctl/bootctl-status.c @@ -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) diff --git a/src/bootctl/bootctl-unlink.c b/src/bootctl/bootctl-unlink.c index b5cc8397989..0d0e7ad076b 100644 --- a/src/bootctl/bootctl-unlink.c +++ b/src/bootctl/bootctl-unlink.c @@ -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) diff --git a/src/bootctl/bootctl.c b/src/bootctl/bootctl.c index ef1116ced72..239a0c92730 100644 --- a/src/bootctl/bootctl.c +++ b/src/bootctl/bootctl.c @@ -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; diff --git a/src/bootctl/bootctl.h b/src/bootctl/bootctl.h index 07e98f85594..d3d6583c024 100644 --- a/src/bootctl/bootctl.h +++ b/src/bootctl/bootctl.h @@ -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 diff --git a/src/kernel-install/kernel-install.c b/src/kernel-install/kernel-install.c index 8c0abba4207..aeded46c22d 100644 --- a/src/kernel-install/kernel-install.c +++ b/src/kernel-install/kernel-install.c @@ -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; diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 2d9906acb9b..c3774a5235f 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -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) diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index 3ff214a09a3..d3383aebb6f 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -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"); diff --git a/src/shared/find-esp.c b/src/shared/find-esp.c index 1d13683f128..d29719785fe 100644 --- a/src/shared/find-esp.c +++ b/src/shared/find-esp.c @@ -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) diff --git a/src/shared/find-esp.h b/src/shared/find-esp.h index 30b7c4a7611..ad02bcd8f3f 100644 --- a/src/shared/find-esp.h +++ b/src/shared/find-esp.h @@ -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); } diff --git a/src/sysupdate/sysupdate-resource.c b/src/sysupdate/sysupdate-resource.c index b819fcd5b85..5865a39e2f1 100644 --- a/src/sysupdate/sysupdate-resource.c +++ b/src/sysupdate/sysupdate-resource.c @@ -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); diff --git a/src/tpm2-setup/tpm2-swtpm.c b/src/tpm2-setup/tpm2-swtpm.c index 4ea6517157e..71ad6b5e9d1 100644 --- a/src/tpm2-setup/tpm2-swtpm.c +++ b/src/tpm2-setup/tpm2-swtpm.c @@ -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); -- 2.47.3