Re: [PATCH 2/2] efi: Align unaccepted memory range to page boundary

From: Tom Lendacky

Date: Mon Feb 16 2026 - 09:52:59 EST


On 2/13/26 09:48, Kiryl Shutsemau (Meta) wrote:
> 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) <kas@xxxxxxxxxx>
> ---
> drivers/firmware/efi/unaccepted_memory.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c
> index c2c067eff634..9ddf3dedd514 100644
> --- a/drivers/firmware/efi/unaccepted_memory.c
> +++ b/drivers/firmware/efi/unaccepted_memory.c
> @@ -35,14 +35,18 @@ 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;
>
> + start = PAGE_ALIGN_DOWN(start);
> + size = PAGE_ALIGN(size);
> + end = start + size;

Should this really be:

end = PAGE_ALIGN(start + size);
start = PAGE_ALIGN_DOWN(start);

?

Thanks,
Tom

> +
> unit_size = unaccepted->unit_size;
>
> /*
> @@ -160,15 +164,19 @@ void accept_memory(phys_addr_t start, unsigned long size)
> 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;
>
> + start = PAGE_ALIGN_DOWN(start);
> + size = PAGE_ALIGN(size);
> + end = start + size;
> +
> unit_size = unaccepted->unit_size;
>
> /*