From: Daan De Meyer Date: Sun, 10 Dec 2023 21:44:25 +0000 (+0100) Subject: bootctl: update/list/remove all instances of systemd-boot in /EFI/BOOT X-Git-Tag: v256-rc1~1447 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=929f41c6528fb630753d4e2f588a8eb6c2f6a609;p=thirdparty%2Fsystemd.git bootctl: update/list/remove all instances of systemd-boot in /EFI/BOOT systemd-boot might be installed in /EFI/BOOT under more names than just /EFI/BOOT/BOOTX64.efi. The prime example is shim which loads its second stage binary from /EFI/BOOT/grubx64.efi. To accomodate use cases where systemd-boot is installed as /EFI/BOOT/grubx64.efi, let's always check the entire /EFI/BOOT directory for binaries that identify as systemd-boot and list/update/remove those as well. Let's keep this somewhat generic though and not install ourselves as grubx64.efi since that would mean having to check for shim which is a can of worms we probably don't want to open. --- diff --git a/src/boot/bootctl-install.c b/src/boot/bootctl-install.c index bacbbb29390..d1bd3c681c7 100644 --- a/src/boot/bootctl-install.c +++ b/src/boot/bootctl-install.c @@ -318,6 +318,46 @@ static int create_subdirs(const char *root, const char * const *subdirs) { return 0; } +static int update_efi_boot_binaries(const char *esp_path, const char *source_path) { + _cleanup_closedir_ DIR *d = NULL; + _cleanup_free_ char *p = NULL; + int r, ret = 0; + + r = chase_and_opendir("/EFI/BOOT", esp_path, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, &p, &d); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_error_errno(r, "Failed to open directory \"%s/EFI/BOOT\": %m", esp_path); + + FOREACH_DIRENT(de, d, break) { + _cleanup_close_ int fd = -EBADF; + _cleanup_free_ char *v = NULL; + + if (!endswith_no_case(de->d_name, ".efi")) + continue; + + fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); + + r = get_file_version(fd, &v); + if (r == -ESRCH) + continue; /* No version information */ + if (r < 0) + return r; + if (startswith(v, "systemd-boot ")) { + _cleanup_free_ char *dest_path = NULL; + + dest_path = path_join(p, de->d_name); + if (!dest_path) + return log_oom(); + + RET_GATHER(ret, copy_file_with_version_check(source_path, dest_path, /* force = */ false)); + } + } + + return ret; +} static int copy_one_file(const char *esp_path, const char *name, bool force) { char *root = IN_SET(arg_install_source, ARG_INSTALL_SOURCE_AUTO, ARG_INSTALL_SOURCE_IMAGE) ? arg_root : NULL; @@ -371,9 +411,12 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) { if (r < 0) return log_error_errno(r, "Failed to resolve path %s under directory %s: %m", v, esp_path); - r = copy_file_with_version_check(source_path, default_dest_path, force); - if (r < 0 && ret == 0) - ret = r; + RET_GATHER(ret, copy_file_with_version_check(source_path, default_dest_path, force)); + + /* If we were installed under any other name in /EFI/BOOT, make sure we update those binaries + * as well. */ + if (!force) + RET_GATHER(ret, update_efi_boot_binaries(esp_path, source_path)); } return ret; @@ -845,9 +888,6 @@ static int remove_boot_efi(const char *esp_path) { if (!endswith_no_case(de->d_name, ".efi")) continue; - if (!startswith_no_case(de->d_name, "boot")) - continue; - fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC); if (fd < 0) return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); diff --git a/src/boot/bootctl-status.c b/src/boot/bootctl-status.c index 16b2eaed072..c8041c4bd1f 100644 --- a/src/boot/bootctl-status.c +++ b/src/boot/bootctl-status.c @@ -187,7 +187,6 @@ static int status_variables(void) { static int enumerate_binaries( const char *esp_path, const char *path, - const char *prefix, char **previous, bool *is_first) { @@ -213,9 +212,6 @@ static int enumerate_binaries( if (!endswith_no_case(de->d_name, ".efi")) continue; - if (prefix && !startswith_no_case(de->d_name, prefix)) - continue; - filename = path_join(p, de->d_name); if (!filename) return log_oom(); @@ -272,11 +268,11 @@ static int status_binaries(const char *esp_path, sd_id128_t partition) { printf(" (/dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR ")", SD_ID128_FORMAT_VAL(partition)); printf("\n"); - r = enumerate_binaries(esp_path, "EFI/systemd", NULL, &last, &is_first); + r = enumerate_binaries(esp_path, "EFI/systemd", &last, &is_first); if (r < 0) goto fail; - k = enumerate_binaries(esp_path, "EFI/BOOT", "boot", &last, &is_first); + k = enumerate_binaries(esp_path, "EFI/BOOT", &last, &is_first); if (k < 0) { r = k; goto fail;