[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] Validate EFI memory descriptors
It turns out that these can be invalid in various ways. Based on code Ard Biesheuvel contributed for Linux. Co-developed-by: Ard Biesheuvel <ardb@xxxxxxxxxx> Signed-off-by: Demi Marie Obenour <demi@xxxxxxxxxxxxxxxxxxxxxx> Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx> --- xen/common/efi/boot.c | 11 +++++------ xen/common/efi/efi.h | 14 ++++++++++++++ xen/common/efi/runtime.c | 13 ++++++------- xen/include/xen/types.h | 1 + 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index b3de1011ee58a67a82a94da050eb1343f4e37faa..dd0376fdf930c2fee35e79a2f2821361c5e15d33 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -591,15 +591,14 @@ static UINTN __initdata esrt = EFI_INVALID_TABLE_ADDR; static size_t __init get_esrt_size(const EFI_MEMORY_DESCRIPTOR *desc) { - size_t available_len, len; + UINT64 available_len, len = efi_memory_descriptor_len(desc); const UINTN physical_start = desc->PhysicalStart; const EFI_SYSTEM_RESOURCE_TABLE *esrt_ptr; - len = desc->NumberOfPages << EFI_PAGE_SHIFT; if ( esrt == EFI_INVALID_TABLE_ADDR ) - return 0; + return 0; /* invalid ESRT */ if ( physical_start > esrt || esrt - physical_start >= len ) - return 0; + return 0; /* ESRT not in this memory region */ /* * The specification requires EfiBootServicesData, but also accept * EfiRuntimeServicesData (for compatibility with buggy firmware) @@ -609,10 +608,10 @@ static size_t __init get_esrt_size(const EFI_MEMORY_DESCRIPTOR *desc) if ( (desc->Type != EfiRuntimeServicesData) && (desc->Type != EfiBootServicesData) && (desc->Type != EfiACPIReclaimMemory) ) - return 0; + return 0; /* memory region cannot contain ESRT */ available_len = len - (esrt - physical_start); if ( available_len <= offsetof(EFI_SYSTEM_RESOURCE_TABLE, Entries) ) - return 0; + return 0; /* ESRT header does not fit in memory region */ available_len -= offsetof(EFI_SYSTEM_RESOURCE_TABLE, Entries); esrt_ptr = (const EFI_SYSTEM_RESOURCE_TABLE *)esrt; if ( (esrt_ptr->FwResourceVersion != diff --git a/xen/common/efi/efi.h b/xen/common/efi/efi.h index c9aa65d506b14de69c90b6538c934747fcf0fb80..f4875138415c23eac42616131a738b7f8e33e56b 100644 --- a/xen/common/efi/efi.h +++ b/xen/common/efi/efi.h @@ -51,3 +51,17 @@ void free_ebmalloc_unused_mem(void); const void *pe_find_section(const void *image_base, const size_t image_size, const CHAR16 *section_name, UINTN *size_out); + +static inline UINT64 +efi_memory_descriptor_len(const EFI_MEMORY_DESCRIPTOR *desc) +{ + uint64_t remaining_space = UINT64_MAX - desc->PhysicalStart; + + if ( desc->PhysicalStart & (EFI_PAGE_SIZE - 1) ) + return 0; /* misaligned start address */ + + if ( desc->NumberOfPages > (remaining_space >> EFI_PAGE_SHIFT) ) + return 0; /* too big */ + + return desc->NumberOfPages << EFI_PAGE_SHIFT; +} diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c index 13b0975866e3a80c46a7e37788012a716a455b6a..b99de230a5464c46b0b6c19b073685b4e0298343 100644 --- a/xen/common/efi/runtime.c +++ b/xen/common/efi/runtime.c @@ -270,18 +270,17 @@ int efi_get_info(uint32_t idx, union xenpf_efi_info *info) for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) { EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; - u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; + uint64_t size, len = efi_memory_descriptor_len(desc); if ( info->mem.addr >= desc->PhysicalStart && - info->mem.addr < desc->PhysicalStart + len ) + info->mem.addr - desc->PhysicalStart < len ) { info->mem.type = desc->Type; info->mem.attr = desc->Attribute; - if ( info->mem.addr + info->mem.size < info->mem.addr || - info->mem.addr + info->mem.size > - desc->PhysicalStart + len ) - info->mem.size = desc->PhysicalStart + len - - info->mem.addr; + size = desc->PhysicalStart + len - info->mem.addr; + if ( info->mem.size > size ) + info->mem.size = size; + return 0; } } diff --git a/xen/include/xen/types.h b/xen/include/xen/types.h index 03f0fe612ed96118614505c39d0e33b946288d6c..255f5a3c91c6be3e8ba4584902563c11bee7f98d 100644 --- a/xen/include/xen/types.h +++ b/xen/include/xen/types.h @@ -25,6 +25,7 @@ #define UINT8_MAX (255) #define UINT16_MAX (65535) #define UINT32_MAX (4294967295U) +#define UINT64_MAX (0xFFFFFFFFFFFFFFFFULL) #define INT_MAX ((int)(~0U>>1)) #define INT_MIN (-INT_MAX - 1) -- Sincerely, Demi Marie Obenour (she/her/hers) Invisible Things Lab
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |