Skip to content

Commit

Permalink
arm64: efi: Limit allocations to 48-bit addressable physical region
Browse files Browse the repository at this point in the history
The UEFI spec does not mention or reason about the configured size of
the virtual address space at all, but it does mention that all memory
should be identity mapped using a page size of 4 KiB.

This means that a LPA2 capable system that has any system memory outside
of the 48-bit addressable physical range and follows the spec to the
letter may serve page allocation requests from regions of memory that
the kernel cannot access unless it was built with LPA2 support and
enables it at runtime.

So let's ensure that all page allocations are limited to the 48-bit
range.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
  • Loading branch information
Ard Biesheuvel committed Dec 7, 2022
1 parent d9f26ae commit a37dac5
Show file tree
Hide file tree
Showing 6 changed files with 13 additions and 3 deletions.
1 change: 1 addition & 0 deletions arch/arm64/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ static inline unsigned long efi_get_kimg_min_align(void)
}

#define EFI_ALLOC_ALIGN SZ_64K
#define EFI_ALLOC_LIMIT ((1UL << 48) - 1)

/*
* On ARM systems, virtually remapped UEFI runtime services are set up in two
Expand Down
2 changes: 2 additions & 0 deletions drivers/firmware/efi/libstub/alignedmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
efi_status_t status;
int slack;

max = min(max, EFI_ALLOC_LIMIT);

if (align < EFI_ALLOC_ALIGN)
align = EFI_ALLOC_ALIGN;

Expand Down
5 changes: 3 additions & 2 deletions drivers/firmware/efi/libstub/arm64-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,11 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
if (status != EFI_SUCCESS) {
if (!check_image_region((u64)_text, kernel_memsize)) {
efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
} else if (IS_ALIGNED((u64)_text, min_kimg_align)) {
} else if (IS_ALIGNED((u64)_text, min_kimg_align) &&
(u64)_end < EFI_ALLOC_LIMIT) {
/*
* Just execute from wherever we were loaded by the
* UEFI PE/COFF loader if the alignment is suitable.
* UEFI PE/COFF loader if the placement is suitable.
*/
*image_addr = (u64)_text;
*reserve_size = 0;
Expand Down
4 changes: 4 additions & 0 deletions drivers/firmware/efi/libstub/efistub.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
#endif

#ifndef EFI_ALLOC_LIMIT
#define EFI_ALLOC_LIMIT ULONG_MAX
#endif

extern bool efi_nochunk;
extern bool efi_nokaslr;
extern int efi_loglevel;
Expand Down
2 changes: 2 additions & 0 deletions drivers/firmware/efi/libstub/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
efi_physical_addr_t alloc_addr;
efi_status_t status;

max = min(max, EFI_ALLOC_LIMIT);

if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE)
return efi_allocate_pages_aligned(size, addr, max,
EFI_ALLOC_ALIGN,
Expand Down
2 changes: 1 addition & 1 deletion drivers/firmware/efi/libstub/randomalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
return 0;

region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
(u64)ULONG_MAX);
(u64)EFI_ALLOC_LIMIT);
if (region_end < size)
return 0;

Expand Down

0 comments on commit a37dac5

Please sign in to comment.