summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDemi Marie Obenour <demi@invisiblethingslab.com>2023-01-19 14:03:56 -0500
committerArd Biesheuvel <ardb@kernel.org>2023-01-22 10:14:15 +0100
commitab03e91e60ce457a90e6aa2c97ca2fa139b73f55 (patch)
treeab0cbfd47accecefac4e738d1b51545729415405
parent2cf9e278efeff8f8bbb9580e2d6760e19795e310 (diff)
efi: memmap: Disregard bogus entries instead of returning them
The ESRT code currently contains two consistency checks on the memory descriptor it obtains, but one of them is both incomplete and can only trigger on invalid descriptors. So let's drop these checks, and instead disregard descriptors entirely if the start address is misaligned, or if the number of pages reaches to or beyond the end of the address space. Note that the memory map as a whole could still be inconsistent: multiple entries might cover the same area, or the address could be outside of the addressable PA space, but validating that goes beyond the scope of these helpers. Also note that since the physical address space is never 64-bits wide, a descriptor that includes the last page of memory is not valid. This is fortunate, since it means that a valid physical address will never be an error pointer and that the length of a memory descriptor in bytes will fit in a 64-bit unsigned integer. Co-developed-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Demi Marie Obenour <demi@invisiblethingslab.com> Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
-rw-r--r--drivers/firmware/efi/efi.c6
-rw-r--r--drivers/firmware/efi/esrt.c9
2 files changed, 7 insertions, 8 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index e7ff692f111d..d295be116039 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -496,6 +496,12 @@ int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
u64 size;
u64 end;
+ /* skip bogus entries (including empty ones) */
+ if ((md->phys_addr & (EFI_PAGE_SIZE - 1)) ||
+ (md->num_pages <= 0) ||
+ (md->num_pages > (U64_MAX - md->phys_addr) >> EFI_PAGE_SHIFT))
+ continue;
+
size = md->num_pages << EFI_PAGE_SHIFT;
end = md->phys_addr + size;
if (phys_addr >= md->phys_addr && phys_addr < end) {
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 2a2f52b017e7..fb9fb70e1004 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -263,15 +263,8 @@ void __init efi_esrt_init(void)
return;
}
- max = efi_mem_desc_end(&md);
- if (max < efi.esrt) {
- pr_err("EFI memory descriptor is invalid. (esrt: %p max: %p)\n",
- (void *)efi.esrt, (void *)max);
- return;
- }
-
+ max = efi_mem_desc_end(&md) - efi.esrt;
size = sizeof(*esrt);
- max -= efi.esrt;
if (max < size) {
pr_err("ESRT header doesn't fit on single memory map entry. (size: %zu max: %zu)\n",