Skip to content

Commit 948a013

Browse files
Kiryl Shutsemau (Meta)ardbiesheuvel
authored andcommitted
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) <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>
1 parent 0862438 commit 948a013

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

drivers/firmware/efi/unaccepted_memory.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,17 @@ void accept_memory(phys_addr_t start, unsigned long size)
3535
struct efi_unaccepted_memory *unaccepted;
3636
unsigned long range_start, range_end;
3737
struct accept_range range, *entry;
38-
phys_addr_t end = start + size;
3938
unsigned long flags;
39+
phys_addr_t end;
4040
u64 unit_size;
4141

4242
unaccepted = efi_get_unaccepted_table();
4343
if (!unaccepted)
4444
return;
4545

46+
end = PAGE_ALIGN(start + size);
47+
start = PAGE_ALIGN_DOWN(start);
48+
4649
unit_size = unaccepted->unit_size;
4750

4851
/*
@@ -160,15 +163,18 @@ void accept_memory(phys_addr_t start, unsigned long size)
160163
bool range_contains_unaccepted_memory(phys_addr_t start, unsigned long size)
161164
{
162165
struct efi_unaccepted_memory *unaccepted;
163-
phys_addr_t end = start + size;
164166
unsigned long flags;
165167
bool ret = false;
168+
phys_addr_t end;
166169
u64 unit_size;
167170

168171
unaccepted = efi_get_unaccepted_table();
169172
if (!unaccepted)
170173
return false;
171174

175+
end = PAGE_ALIGN(start + size);
176+
start = PAGE_ALIGN_DOWN(start);
177+
172178
unit_size = unaccepted->unit_size;
173179

174180
/*

0 commit comments

Comments
 (0)