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
a98a6eb95c. Hence, let's clean this up,
and pin the inode we really care about and return it.
This commit is contained in:
Lennart Poettering
2026-04-13 18:04:29 +02:00
parent 4712d70669
commit 853d0649d5
16 changed files with 293 additions and 273 deletions

View 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)

View 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)

View 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);
if (c->esp_fd >= 0)
return c->esp_fd;
_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);
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)

View 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;

View 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);

View 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)

View 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)

View 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;

View 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

View 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;

View 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)

View 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");

View 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 (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 (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 (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)

View 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);
}

View 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);

View 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);