From 6b8770b96b403407b371e704b4afdcd0851deb3b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Jun 2025 14:03:57 +0200 Subject: [PATCH] bootctl: when updating everything check PE machine type Let's never accidentally over-write foreign-arch PE binaries with native ones. Fixes: #33413 --- src/bootctl/bootctl-install.c | 33 ++++++++++++++++++++++++--------- src/shared/pe-binary.c | 11 +++++++++++ src/shared/pe-binary.h | 1 + 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/bootctl/bootctl-install.c b/src/bootctl/bootctl-install.c index 426a821168c..f751914b58d 100644 --- a/src/bootctl/bootctl-install.c +++ b/src/bootctl/bootctl-install.c @@ -28,6 +28,7 @@ #include "openssl-util.h" #include "parse-argument.h" #include "path-util.h" +#include "pe-binary.h" #include "rm-rf.h" #include "stat-util.h" #include "string-util.h" @@ -356,20 +357,27 @@ static int update_efi_boot_binaries(const char *esp_path, const char *source_pat if (fd < 0) return log_error_errno(fd, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); + r = pe_is_native_fd(fd); + if (r < 0) { + log_warning_errno(r, "Failed to detect if \"%s/%s\" is native architecture, ignoring: %m", p, de->d_name); + continue; + } + if (r == 0) + continue; + 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; + if (!startswith(v, "systemd-boot ")) + continue; - dest_path = path_join(p, de->d_name); - if (!dest_path) - return log_oom(); + _cleanup_free_ char *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)); - } + RET_GATHER(ret, copy_file_with_version_check(source_path, dest_path, /* force = */ false)); } return ret; @@ -1109,14 +1117,21 @@ static int remove_boot_efi(const char *esp_path) { if (fd < 0) return log_error_errno(fd, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); + r = pe_is_native_fd(fd); + if (r < 0) { + log_warning_errno(r, "Failed to detect if \"%s/%s\" is native architecture, ignoring: %m", p, de->d_name); + continue; + } + if (r == 0) + continue; + r = get_file_version(fd, &v); if (r == -ESRCH) continue; /* No version information */ if (r < 0) return r; if (startswith(v, "systemd-boot ")) { - r = unlinkat(dirfd(d), de->d_name, 0); - if (r < 0) + if (unlinkat(dirfd(d), de->d_name, 0) < 0) return log_error_errno(errno, "Failed to remove \"%s/%s\": %m", p, de->d_name); log_info("Removed \"%s/%s\".", p, de->d_name); diff --git a/src/shared/pe-binary.c b/src/shared/pe-binary.c index 627c59cac8d..1dfda07142c 100644 --- a/src/shared/pe-binary.c +++ b/src/shared/pe-binary.c @@ -290,6 +290,17 @@ bool pe_is_native(const PeHeader *pe_header) { #endif } +int pe_is_native_fd(int fd) { + _cleanup_free_ PeHeader *pe_header = NULL; + int r; + + r = pe_load_headers(fd, /* ret_dos_header= */ NULL, &pe_header); + if (r < 0) + return r; + + return pe_is_native(pe_header); +} + /* Implements: * * https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/authenticode_pe.docx diff --git a/src/shared/pe-binary.h b/src/shared/pe-binary.h index 2daaf7eea9f..2579dd9ae8b 100644 --- a/src/shared/pe-binary.h +++ b/src/shared/pe-binary.h @@ -149,6 +149,7 @@ bool pe_is_uki(const PeHeader *pe_header, const IMAGE_SECTION_HEADER *sections); bool pe_is_addon(const PeHeader *pe_header, const IMAGE_SECTION_HEADER *sections); bool pe_is_native(const PeHeader *pe_header); +int pe_is_native_fd(int fd); int pe_hash(int fd, const EVP_MD *md, void **ret_hash, size_t *ret_hash_size); -- 2.47.3