From: Kiryl Shutsemau (Meta) Date: Tue, 17 Feb 2026 10:49:57 +0000 (+0000) Subject: efi: Align unaccepted memory range to page boundary X-Git-Tag: v7.0-rc1~38^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=948a013a54c47d5eba06e644b99d4927a8bc62f8;p=thirdparty%2Flinux.git efi: Align unaccepted memory range to page boundary The accept_memory() and range_contains_unaccepted_memory() functions employ a "guard page" logic to prevent crashes with load_unaligned_zeropad(). This logic extends the range to be accepted (or checked) by one unit_size if the end of the range is aligned to a unit_size boundary. However, if the caller passes a range that is not page-aligned, the 'end' of the range might not be numerically aligned to unit_size, even if it covers the last page of a unit. This causes the "if (!(end % unit_size))" check to fail, skipping the necessary extension and leaving the next unit unaccepted, which can lead to a kernel panic when accessed by load_unaligned_zeropad(). Align the start address down and the size up to the nearest page boundary before performing the unit_size alignment check. This ensures that the guard unit is correctly added when the range effectively ends on a unit boundary. Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Tom Lendacky Acked-by: Mike Rapoport (Microsoft) Signed-off-by: Ard Biesheuvel --- diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c index c2c067eff634..4a8ec8d6a571 100644 --- a/drivers/firmware/efi/unaccepted_memory.c +++ b/drivers/firmware/efi/unaccepted_memory.c @@ -35,14 +35,17 @@ void accept_memory(phys_addr_t start, unsigned long size) struct efi_unaccepted_memory *unaccepted; unsigned long range_start, range_end; struct accept_range range, *entry; - phys_addr_t end = start + size; unsigned long flags; + phys_addr_t end; u64 unit_size; unaccepted = efi_get_unaccepted_table(); if (!unaccepted) return; + end = PAGE_ALIGN(start + size); + start = PAGE_ALIGN_DOWN(start); + unit_size = unaccepted->unit_size; /* @@ -160,15 +163,18 @@ retry: bool range_contains_unaccepted_memory(phys_addr_t start, unsigned long size) { struct efi_unaccepted_memory *unaccepted; - phys_addr_t end = start + size; unsigned long flags; bool ret = false; + phys_addr_t end; u64 unit_size; unaccepted = efi_get_unaccepted_table(); if (!unaccepted) return false; + end = PAGE_ALIGN(start + size); + start = PAGE_ALIGN_DOWN(start); + unit_size = unaccepted->unit_size; /*