Some UEFI implementations for ARM64 devices apply strict permissions on
the different allocation types.  In these implementations, DATA
allocations have XN (execute never) permissions, preventing code execution
from those pages.

On these implementations, the Linux kernel is loaded to DATA pages, which
causes a permission fault when GRUB attempts to kick off the kernel.  This
results in a device crash.

Fix this by allocating CODE pages for the Linux kernel.

Signed-off-by: Jeffrey Hugo <jeffrey.l.h...@gmail.com>
---
 grub-core/kern/efi/mm.c        | 8 ++++++++
 grub-core/loader/arm64/linux.c | 2 +-
 include/grub/efi/efi.h         | 2 ++
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index b02fab1b1..725695e01 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -156,6 +156,14 @@ grub_efi_allocate_any_pages (grub_efi_uintn_t pages)
                                       GRUB_EFI_LOADER_DATA);
 }
 
+void *
+grub_efi_allocate_code_pages (grub_efi_uintn_t pages)
+{
+  return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS,
+                                      pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+                                      GRUB_EFI_LOADER_CODE);
+}
+
 void *
 grub_efi_allocate_fixed (grub_efi_physical_address_t address,
                         grub_efi_uintn_t pages)
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index ef3e9f944..877839072 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -313,7 +313,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   grub_loader_unset();
 
   grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
-  kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES 
(kernel_size));
+  kernel_addr = grub_efi_allocate_code_pages (GRUB_EFI_BYTES_TO_PAGES 
(kernel_size));
   grub_dprintf ("linux", "kernel numpages: %lld\n",
                (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
   if (!kernel_addr)
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index e90e00dc4..697cabcd6 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -47,6 +47,8 @@ EXPORT_FUNC(grub_efi_allocate_fixed) 
(grub_efi_physical_address_t address,
                                      grub_efi_uintn_t pages);
 void *
 EXPORT_FUNC(grub_efi_allocate_any_pages) (grub_efi_uintn_t pages);
+void *
+EXPORT_FUNC(grub_efi_allocate_code_pages) (grub_efi_uintn_t pages);
 void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address,
                                       grub_efi_uintn_t pages);
 grub_efi_uintn_t EXPORT_FUNC(grub_efi_find_mmap_size) (void);
-- 
2.17.1


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to