| From 5a62ebb47b8662c5ed10f31a6988f70f4320b343 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 17 Feb 2026 10:49:56 +0000 |
| Subject: efi: Fix reservation of unaccepted memory table |
| |
| From: Kiryl Shutsemau (Meta) <kas@kernel.org> |
| |
| [ Upstream commit 0862438c90487e79822d5647f854977d50381505 ] |
| |
| The reserve_unaccepted() function incorrectly calculates the size of the |
| memblock reservation for the unaccepted memory table. It aligns the |
| size of the table, but fails to account for cases where the table's |
| starting physical address (efi.unaccepted) is not page-aligned. |
| |
| If the table starts at an offset within a page and its end crosses into |
| a subsequent page that the aligned size does not cover, the end of the |
| table will not be reserved. This can lead to the table being overwritten |
| or inaccessible, causing a kernel panic in accept_memory(). |
| |
| This issue was observed when starting Intel TDX VMs with specific memory |
| sizes (e.g., > 64GB). |
| |
| Fix this by calculating the end address first (including the unaligned |
| start) and then aligning it up, ensuring the entire range is covered |
| by the reservation. |
| |
| Fixes: 8dbe33956d96 ("efi/unaccepted: Make sure unaccepted table is mapped") |
| Reported-by: Moritz Sanft <ms@edgeless.systems> |
| Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org> |
| Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> |
| Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> |
| Signed-off-by: Ard Biesheuvel <ardb@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/firmware/efi/efi.c | 8 ++++---- |
| 1 file changed, 4 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c |
| index 1ab161e00c867..ef55e3851b362 100644 |
| --- a/drivers/firmware/efi/efi.c |
| +++ b/drivers/firmware/efi/efi.c |
| @@ -648,13 +648,13 @@ static __init int match_config_table(const efi_guid_t *guid, |
| |
| static __init void reserve_unaccepted(struct efi_unaccepted_memory *unaccepted) |
| { |
| - phys_addr_t start, size; |
| + phys_addr_t start, end; |
| |
| start = PAGE_ALIGN_DOWN(efi.unaccepted); |
| - size = PAGE_ALIGN(sizeof(*unaccepted) + unaccepted->size); |
| + end = PAGE_ALIGN(efi.unaccepted + sizeof(*unaccepted) + unaccepted->size); |
| |
| - memblock_add(start, size); |
| - memblock_reserve(start, size); |
| + memblock_add(start, end - start); |
| + memblock_reserve(start, end - start); |
| } |
| |
| int __init efi_config_parse_tables(const efi_config_table_t *config_tables, |
| -- |
| 2.51.0 |
| |