Commit 9cf42bca authored by Ard Biesheuvel's avatar Ard Biesheuvel

efi: libstub: use EFI_LOADER_CODE region when moving the kernel in memory

The EFI spec is not very clear about which permissions are being given
when allocating pages of a certain type. However, it is quite obvious
that EFI_LOADER_CODE is more likely to permit execution than
EFI_LOADER_DATA, which becomes relevant once we permit booting the
kernel proper with the firmware's 1:1 mapping still active.

Ostensibly, recent systems such as the Surface Pro X grant executable
permissions to EFI_LOADER_CODE regions but not EFI_LOADER_DATA regions.
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent 97712289
...@@ -22,7 +22,8 @@ ...@@ -22,7 +22,8 @@
* Return: status code * Return: status code
*/ */
efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr, efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
unsigned long max, unsigned long align) unsigned long max, unsigned long align,
int memory_type)
{ {
efi_physical_addr_t alloc_addr; efi_physical_addr_t alloc_addr;
efi_status_t status; efi_status_t status;
...@@ -36,7 +37,7 @@ efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr, ...@@ -36,7 +37,7 @@ efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
slack = align / EFI_PAGE_SIZE - 1; slack = align / EFI_PAGE_SIZE - 1;
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS, status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
EFI_LOADER_DATA, size / EFI_PAGE_SIZE + slack, memory_type, size / EFI_PAGE_SIZE + slack,
&alloc_addr); &alloc_addr);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
return status; return status;
......
...@@ -102,7 +102,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -102,7 +102,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
* locate the kernel at a randomized offset in physical memory. * locate the kernel at a randomized offset in physical memory.
*/ */
status = efi_random_alloc(*reserve_size, min_kimg_align, status = efi_random_alloc(*reserve_size, min_kimg_align,
reserve_addr, phys_seed); reserve_addr, phys_seed,
EFI_LOADER_CODE);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
efi_warn("efi_random_alloc() failed: 0x%lx\n", status); efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
} else { } else {
...@@ -123,7 +124,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -123,7 +124,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
} }
status = efi_allocate_pages_aligned(*reserve_size, reserve_addr, status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
ULONG_MAX, min_kimg_align); ULONG_MAX, min_kimg_align,
EFI_LOADER_CODE);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_err("Failed to relocate kernel\n"); efi_err("Failed to relocate kernel\n");
......
...@@ -880,7 +880,8 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size, ...@@ -880,7 +880,8 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
efi_status_t efi_get_random_bytes(unsigned long size, u8 *out); efi_status_t efi_get_random_bytes(unsigned long size, u8 *out);
efi_status_t efi_random_alloc(unsigned long size, unsigned long align, efi_status_t efi_random_alloc(unsigned long size, unsigned long align,
unsigned long *addr, unsigned long random_seed); unsigned long *addr, unsigned long random_seed,
int memory_type);
efi_status_t check_platform_features(void); efi_status_t check_platform_features(void);
...@@ -905,7 +906,8 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr, ...@@ -905,7 +906,8 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
unsigned long max); unsigned long max);
efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr, efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
unsigned long max, unsigned long align); unsigned long max, unsigned long align,
int memory_type);
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
unsigned long *addr, unsigned long min); unsigned long *addr, unsigned long min);
......
...@@ -91,7 +91,8 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr, ...@@ -91,7 +91,8 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE) if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE)
return efi_allocate_pages_aligned(size, addr, max, return efi_allocate_pages_aligned(size, addr, max,
EFI_ALLOC_ALIGN); EFI_ALLOC_ALIGN,
EFI_LOADER_DATA);
alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1; alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1;
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS, status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
......
...@@ -53,7 +53,8 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md, ...@@ -53,7 +53,8 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
efi_status_t efi_random_alloc(unsigned long size, efi_status_t efi_random_alloc(unsigned long size,
unsigned long align, unsigned long align,
unsigned long *addr, unsigned long *addr,
unsigned long random_seed) unsigned long random_seed,
int memory_type)
{ {
unsigned long total_slots = 0, target_slot; unsigned long total_slots = 0, target_slot;
unsigned long total_mirrored_slots = 0; unsigned long total_mirrored_slots = 0;
...@@ -118,7 +119,7 @@ efi_status_t efi_random_alloc(unsigned long size, ...@@ -118,7 +119,7 @@ efi_status_t efi_random_alloc(unsigned long size,
pages = size / EFI_PAGE_SIZE; pages = size / EFI_PAGE_SIZE;
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS, status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
EFI_LOADER_DATA, pages, &target); memory_type, pages, &target);
if (status == EFI_SUCCESS) if (status == EFI_SUCCESS)
*addr = target; *addr = target;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment