diff options
author | Heinrich Schuchardt | 2019-05-11 08:21:17 +0200 |
---|---|---|
committer | Heinrich Schuchardt | 2019-05-12 20:54:22 +0200 |
commit | f756fe83b0d6e189dd524346d22f668d0861e573 (patch) | |
tree | 9462ec2536eabca5da0e8600822bb7e5fc77b075 /lib | |
parent | 735fd22800bbe3177edf1491a26794427541102d (diff) |
efi_loader: AllocateAdress error handling
If AllocatePages() is called with AllocateAddress, the UEFI spec requires
to return EFI_NOT_FOUND in case the memory page does not exist.
The UEFI SCT II 2017 spec additionally requires to return EFI_NOT_FOUND if
the page is already allocated.
Check that *Memory refers to an unallocated page.
UEFI SCT II (2017): AllocatePages(), 5.1.2.1.9 - 5.1.2.1.10
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/efi_memory.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index adbeb1db6b7..11d55470072 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -330,10 +330,11 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, * Page alignment is not checked as this is not a requirement of * efi_free_pool(). * - * @addr: address of page to be freed - * Return: status code + * @addr: address of page to be freed + * @must_be_allocated: return success if the page is allocated + * Return: status code */ -static efi_status_t efi_check_allocated(u64 addr) +static efi_status_t efi_check_allocated(u64 addr, bool must_be_allocated) { struct efi_mem_list *item; @@ -344,7 +345,8 @@ static efi_status_t efi_check_allocated(u64 addr) u64 end = start + (item->desc.num_pages << EFI_PAGE_SHIFT); if (addr >= start && addr < end) { - if (item->desc.type != EFI_CONVENTIONAL_MEMORY) + if (must_be_allocated ^ + (item->desc.type == EFI_CONVENTIONAL_MEMORY)) return EFI_SUCCESS; else return EFI_NOT_FOUND; @@ -438,6 +440,11 @@ efi_status_t efi_allocate_pages(int type, int memory_type, break; case EFI_ALLOCATE_ADDRESS: /* Exact address, reserve it. The addr is already in *memory. */ + r = efi_check_allocated(*memory, false); + if (r != EFI_SUCCESS) { + r = EFI_NOT_FOUND; + break; + } addr = *memory; break; default: @@ -488,7 +495,7 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) uint64_t r = 0; efi_status_t ret; - ret = efi_check_allocated(memory); + ret = efi_check_allocated(memory, true); if (ret != EFI_SUCCESS) return ret; @@ -555,7 +562,7 @@ efi_status_t efi_free_pool(void *buffer) efi_status_t ret; struct efi_pool_allocation *alloc; - ret = efi_check_allocated((uintptr_t)buffer); + ret = efi_check_allocated((uintptr_t)buffer, true); if (ret != EFI_SUCCESS) return ret; |