You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
571 lines
19 KiB
571 lines
19 KiB
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
|
From: Peter Jones <pjones@redhat.com> |
|
Date: Tue, 22 Mar 2022 10:57:07 -0400 |
|
Subject: [PATCH] nx: set attrs in our kernel loaders |
|
|
|
For NX, our kernel loaders need to set write and execute page |
|
permissions on allocated pages and the stack. |
|
|
|
This patch adds those calls. |
|
|
|
Signed-off-by: Peter Jones <pjones@redhat.com> |
|
[rharwood: fix aarch64 callsites] |
|
(cherry-picked from commit a9f79a997f01a83b36cdfa89ef2e72ac2a17c06c) |
|
[rharwood: uninitialized stack_attrs, double verification] |
|
Signed-off-by: Robbie Harwood <rharwood@redhat.com> |
|
--- |
|
grub-core/kern/efi/mm.c | 78 ++++++++++++++++++ |
|
grub-core/loader/arm64/linux.c | 16 +++- |
|
grub-core/loader/arm64/xen_boot.c | 4 +- |
|
grub-core/loader/efi/chainloader.c | 11 +++ |
|
grub-core/loader/efi/linux.c | 164 ++++++++++++++++++++++++++++++++++++- |
|
grub-core/loader/i386/efi/linux.c | 26 +++++- |
|
grub-core/loader/i386/linux.c | 5 ++ |
|
include/grub/efi/efi.h | 6 +- |
|
include/grub/efi/linux.h | 17 +++- |
|
include/grub/efi/pe32.h | 2 + |
|
10 files changed, 314 insertions(+), 15 deletions(-) |
|
|
|
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c |
|
index 2c33758ed7..88364d764c 100644 |
|
--- a/grub-core/kern/efi/mm.c |
|
+++ b/grub-core/kern/efi/mm.c |
|
@@ -610,6 +610,82 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, |
|
} |
|
#endif |
|
|
|
+grub_addr_t grub_stack_addr = (grub_addr_t)-1ll; |
|
+grub_size_t grub_stack_size = 0; |
|
+ |
|
+static void |
|
+grub_nx_init (void) |
|
+{ |
|
+ grub_uint64_t attrs, stack_attrs; |
|
+ grub_err_t err; |
|
+ grub_addr_t stack_current, stack_end; |
|
+ const grub_uint64_t page_size = 4096; |
|
+ const grub_uint64_t page_mask = ~(page_size - 1); |
|
+ |
|
+ /* |
|
+ * These are to confirm that the flags are working as expected when |
|
+ * debugging. |
|
+ */ |
|
+ attrs = 0; |
|
+ stack_current = (grub_addr_t)grub_nx_init & page_mask; |
|
+ err = grub_get_mem_attrs (stack_current, page_size, &attrs); |
|
+ if (err) |
|
+ { |
|
+ grub_dprintf ("nx", |
|
+ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", |
|
+ stack_current, err); |
|
+ grub_error_pop (); |
|
+ } |
|
+ else |
|
+ grub_dprintf ("nx", "page attrs for grub_nx_init (%p) are %c%c%c\n", |
|
+ grub_dl_load_core, |
|
+ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', |
|
+ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', |
|
+ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); |
|
+ |
|
+ stack_current = (grub_addr_t)&stack_current & page_mask; |
|
+ err = grub_get_mem_attrs (stack_current, page_size, &stack_attrs); |
|
+ if (err) |
|
+ { |
|
+ grub_dprintf ("nx", |
|
+ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", |
|
+ stack_current, err); |
|
+ grub_error_pop (); |
|
+ } |
|
+ else |
|
+ { |
|
+ attrs = stack_attrs; |
|
+ grub_dprintf ("nx", "page attrs for stack (%p) are %c%c%c\n", |
|
+ &attrs, |
|
+ (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', |
|
+ (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-', |
|
+ (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-'); |
|
+ } |
|
+ |
|
+ for (stack_end = stack_current + page_size ; |
|
+ !(attrs & GRUB_MEM_ATTR_R); |
|
+ stack_end += page_size) |
|
+ { |
|
+ err = grub_get_mem_attrs (stack_current, page_size, &attrs); |
|
+ if (err) |
|
+ { |
|
+ grub_dprintf ("nx", |
|
+ "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n", |
|
+ stack_current, err); |
|
+ grub_error_pop (); |
|
+ break; |
|
+ } |
|
+ } |
|
+ if (stack_end > stack_current) |
|
+ { |
|
+ grub_stack_addr = stack_current; |
|
+ grub_stack_size = stack_end - stack_current; |
|
+ grub_dprintf ("nx", |
|
+ "detected stack from 0x%"PRIxGRUB_ADDR" to 0x%"PRIxGRUB_ADDR"\n", |
|
+ grub_stack_addr, grub_stack_addr + grub_stack_size - 1); |
|
+ } |
|
+} |
|
+ |
|
void |
|
grub_efi_mm_init (void) |
|
{ |
|
@@ -623,6 +699,8 @@ grub_efi_mm_init (void) |
|
grub_efi_uint64_t required_pages; |
|
int mm_status; |
|
|
|
+ grub_nx_init (); |
|
+ |
|
/* Prepare a memory region to store two memory maps. */ |
|
memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); |
|
if (! memory_map) |
|
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c |
|
index bcc6ef46e9..70db5a6e0b 100644 |
|
--- a/grub-core/loader/arm64/linux.c |
|
+++ b/grub-core/loader/arm64/linux.c |
|
@@ -173,7 +173,8 @@ free_params (void) |
|
} |
|
|
|
grub_err_t |
|
-grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) |
|
+grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args, |
|
+ int nx_supported) |
|
{ |
|
grub_err_t retval; |
|
|
|
@@ -183,7 +184,8 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) |
|
|
|
grub_dprintf ("linux", "linux command line: '%s'\n", args); |
|
|
|
- retval = grub_efi_linux_boot ((char *)addr, handover_offset, (void *)addr); |
|
+ retval = grub_efi_linux_boot (addr, size, handover_offset, |
|
+ (void *)addr, nx_supported); |
|
|
|
/* Never reached... */ |
|
free_params(); |
|
@@ -193,7 +195,10 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args) |
|
static grub_err_t |
|
grub_linux_boot (void) |
|
{ |
|
- return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, linux_args)); |
|
+ return grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, |
|
+ (grub_size_t)kernel_size, |
|
+ linux_args, |
|
+ 0); |
|
} |
|
|
|
static grub_err_t |
|
@@ -342,6 +347,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
grub_uint32_t align; |
|
void *kernel = NULL; |
|
int rc; |
|
+ int nx_supported = 1; |
|
|
|
grub_dl_ref (my_mod); |
|
|
|
@@ -389,6 +395,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); |
|
grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); |
|
|
|
+ err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported); |
|
+ if (err != GRUB_ERR_NONE) |
|
+ goto fail; |
|
+ |
|
grub_loader_unset(); |
|
|
|
kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); |
|
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c |
|
index d9b7a9ba40..6e7e920416 100644 |
|
--- a/grub-core/loader/arm64/xen_boot.c |
|
+++ b/grub-core/loader/arm64/xen_boot.c |
|
@@ -266,7 +266,9 @@ xen_boot (void) |
|
return err; |
|
|
|
return grub_arch_efi_linux_boot_image (xen_hypervisor->start, |
|
- xen_hypervisor->cmdline); |
|
+ xen_hypervisor->size, |
|
+ xen_hypervisor->cmdline, |
|
+ 0); |
|
} |
|
|
|
static void |
|
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c |
|
index 8ef508beca..6ac69f0f59 100644 |
|
--- a/grub-core/loader/efi/chainloader.c |
|
+++ b/grub-core/loader/efi/chainloader.c |
|
@@ -1071,6 +1071,17 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), |
|
goto fail; |
|
} |
|
|
|
+ /* |
|
+ * The OS kernel is going to set its own permissions when it takes over |
|
+ * paging a few million instructions from now, and load_image() will set up |
|
+ * anything that's needed based on the section headers, so there's no point |
|
+ * in doing anything but clearing the protection bits here. |
|
+ */ |
|
+ grub_dprintf("nx", "setting attributes for %p (%lu bytes) to %llx\n", |
|
+ (void *)(grub_addr_t)address, fsize, 0llu); |
|
+ grub_update_mem_attrs (address, fsize, |
|
+ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X, 0); |
|
+ |
|
#if defined (__i386__) || defined (__x86_64__) |
|
if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header)) |
|
{ |
|
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c |
|
index 9260731c10..dcc9ea40ea 100644 |
|
--- a/grub-core/loader/efi/linux.c |
|
+++ b/grub-core/loader/efi/linux.c |
|
@@ -66,16 +66,127 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size) |
|
|
|
#pragma GCC diagnostic push |
|
#pragma GCC diagnostic ignored "-Wcast-align" |
|
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" |
|
+ |
|
+grub_err_t |
|
+grub_efi_check_nx_image_support (grub_addr_t kernel_addr, |
|
+ grub_size_t kernel_size, |
|
+ int *nx_supported) |
|
+{ |
|
+ struct grub_dos_header *doshdr; |
|
+ grub_size_t sz = sizeof (*doshdr); |
|
+ |
|
+ struct grub_pe32_header_32 *pe32; |
|
+ struct grub_pe32_header_64 *pe64; |
|
+ |
|
+ int image_is_compatible = 0; |
|
+ int is_64_bit; |
|
+ |
|
+ if (kernel_size < sz) |
|
+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); |
|
+ |
|
+ doshdr = (void *)kernel_addr; |
|
+ |
|
+ if ((doshdr->magic & 0xffff) != GRUB_DOS_MAGIC) |
|
+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel DOS magic is invalid")); |
|
+ |
|
+ sz = doshdr->lfanew + sizeof (*pe32); |
|
+ if (kernel_size < sz) |
|
+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); |
|
+ |
|
+ pe32 = (struct grub_pe32_header_32 *)(kernel_addr + doshdr->lfanew); |
|
+ pe64 = (struct grub_pe32_header_64 *)pe32; |
|
+ |
|
+ if (grub_memcmp (pe32->signature, GRUB_PE32_SIGNATURE, |
|
+ GRUB_PE32_SIGNATURE_SIZE) != 0) |
|
+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel PE magic is invalid")); |
|
+ |
|
+ switch (pe32->coff_header.machine) |
|
+ { |
|
+ case GRUB_PE32_MACHINE_ARMTHUMB_MIXED: |
|
+ case GRUB_PE32_MACHINE_I386: |
|
+ case GRUB_PE32_MACHINE_RISCV32: |
|
+ is_64_bit = 0; |
|
+ break; |
|
+ case GRUB_PE32_MACHINE_ARM64: |
|
+ case GRUB_PE32_MACHINE_IA64: |
|
+ case GRUB_PE32_MACHINE_RISCV64: |
|
+ case GRUB_PE32_MACHINE_X86_64: |
|
+ is_64_bit = 1; |
|
+ break; |
|
+ default: |
|
+ return grub_error (GRUB_ERR_BAD_OS, N_("PE machine type 0x%04hx unknown"), |
|
+ pe32->coff_header.machine); |
|
+ } |
|
+ |
|
+ if (is_64_bit) |
|
+ { |
|
+ sz = doshdr->lfanew + sizeof (*pe64); |
|
+ if (kernel_size < sz) |
|
+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small")); |
|
+ |
|
+ if (pe64->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) |
|
+ image_is_compatible = 1; |
|
+ } |
|
+ else |
|
+ { |
|
+ if (pe32->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT) |
|
+ image_is_compatible = 1; |
|
+ } |
|
+ |
|
+ *nx_supported = image_is_compatible; |
|
+ return GRUB_ERR_NONE; |
|
+} |
|
+ |
|
+grub_err_t |
|
+grub_efi_check_nx_required (int *nx_required) |
|
+{ |
|
+ grub_efi_status_t status; |
|
+ grub_efi_guid_t guid = GRUB_EFI_SHIM_LOCK_GUID; |
|
+ grub_size_t mok_policy_sz = 0; |
|
+ char *mok_policy = NULL; |
|
+ grub_uint32_t mok_policy_attrs = 0; |
|
+ |
|
+ status = grub_efi_get_variable_with_attributes ("MokPolicy", &guid, |
|
+ &mok_policy_sz, |
|
+ (void **)&mok_policy, |
|
+ &mok_policy_attrs); |
|
+ if (status == GRUB_EFI_NOT_FOUND || |
|
+ mok_policy_sz == 0 || |
|
+ mok_policy == NULL) |
|
+ { |
|
+ *nx_required = 0; |
|
+ return GRUB_ERR_NONE; |
|
+ } |
|
+ |
|
+ *nx_required = 0; |
|
+ if (mok_policy_sz < 1 || |
|
+ mok_policy_attrs != (GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | |
|
+ GRUB_EFI_VARIABLE_RUNTIME_ACCESS) || |
|
+ (mok_policy[mok_policy_sz-1] & GRUB_MOK_POLICY_NX_REQUIRED)) |
|
+ *nx_required = 1; |
|
+ |
|
+ return GRUB_ERR_NONE; |
|
+} |
|
|
|
typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); |
|
|
|
grub_err_t |
|
-grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, |
|
- void *kernel_params) |
|
+grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size, |
|
+ grub_off_t handover_offset, void *kernel_params, |
|
+ int nx_supported) |
|
{ |
|
grub_efi_loaded_image_t *loaded_image = NULL; |
|
handover_func hf; |
|
int offset = 0; |
|
+ grub_uint64_t stack_set_attrs = GRUB_MEM_ATTR_R | |
|
+ GRUB_MEM_ATTR_W | |
|
+ GRUB_MEM_ATTR_X; |
|
+ grub_uint64_t stack_clear_attrs = 0; |
|
+ grub_uint64_t kernel_set_attrs = stack_set_attrs; |
|
+ grub_uint64_t kernel_clear_attrs = stack_clear_attrs; |
|
+ grub_uint64_t attrs; |
|
+ int nx_required = 0; |
|
|
|
#ifdef __x86_64__ |
|
offset = 512; |
|
@@ -88,12 +199,57 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, |
|
*/ |
|
loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); |
|
if (loaded_image) |
|
- loaded_image->image_base = kernel_addr; |
|
+ loaded_image->image_base = (void *)kernel_addr; |
|
else |
|
grub_dprintf ("linux", "Loaded Image base address could not be set\n"); |
|
|
|
grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n", |
|
- kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params); |
|
+ (void *)kernel_addr, (void *)handover_offset, kernel_params); |
|
+ |
|
+ |
|
+ if (nx_required && !nx_supported) |
|
+ return grub_error (GRUB_ERR_BAD_OS, N_("kernel does not support NX loading required by policy")); |
|
+ |
|
+ if (nx_supported) |
|
+ { |
|
+ kernel_set_attrs &= ~GRUB_MEM_ATTR_W; |
|
+ kernel_clear_attrs |= GRUB_MEM_ATTR_W; |
|
+ stack_set_attrs &= ~GRUB_MEM_ATTR_X; |
|
+ stack_clear_attrs |= GRUB_MEM_ATTR_X; |
|
+ } |
|
+ |
|
+ grub_dprintf ("nx", "Setting attributes for 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to r%cx\n", |
|
+ kernel_addr, kernel_addr + kernel_size - 1, |
|
+ (kernel_set_attrs & GRUB_MEM_ATTR_W) ? 'w' : '-'); |
|
+ grub_update_mem_attrs (kernel_addr, kernel_size, |
|
+ kernel_set_attrs, kernel_clear_attrs); |
|
+ |
|
+ grub_get_mem_attrs (kernel_addr, 4096, &attrs); |
|
+ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", |
|
+ (grub_addr_t)kernel_addr, |
|
+ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", |
|
+ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", |
|
+ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); |
|
+ if (grub_stack_addr != (grub_addr_t)-1ll) |
|
+ { |
|
+ grub_dprintf ("nx", "Setting attributes for stack at 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to rw%c\n", |
|
+ grub_stack_addr, grub_stack_addr + grub_stack_size - 1, |
|
+ (stack_set_attrs & GRUB_MEM_ATTR_X) ? 'x' : '-'); |
|
+ grub_update_mem_attrs (grub_stack_addr, grub_stack_size, |
|
+ stack_set_attrs, stack_clear_attrs); |
|
+ |
|
+ grub_get_mem_attrs (grub_stack_addr, 4096, &attrs); |
|
+ grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n", |
|
+ grub_stack_addr, |
|
+ (attrs & GRUB_MEM_ATTR_R) ? "r" : "-", |
|
+ (attrs & GRUB_MEM_ATTR_W) ? "w" : "-", |
|
+ (attrs & GRUB_MEM_ATTR_X) ? "x" : "-"); |
|
+ } |
|
+ |
|
+#if defined(__i386__) || defined(__x86_64__) |
|
+ asm volatile ("cli"); |
|
+#endif |
|
+ |
|
hf = (handover_func)((char *)kernel_addr + handover_offset + offset); |
|
hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); |
|
|
|
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c |
|
index b832c85728..dc98077378 100644 |
|
--- a/grub-core/loader/i386/efi/linux.c |
|
+++ b/grub-core/loader/i386/efi/linux.c |
|
@@ -45,7 +45,7 @@ struct grub_linuxefi_context { |
|
grub_uint32_t handover_offset; |
|
struct linux_kernel_params *params; |
|
char *cmdline; |
|
- |
|
+ int nx_supported; |
|
void *initrd_mem; |
|
}; |
|
|
|
@@ -111,13 +111,19 @@ kernel_alloc(grub_efi_uintn_t size, |
|
pages = BYTES_TO_PAGES(size); |
|
grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n", |
|
(unsigned long)pages, (void *)(unsigned long)max); |
|
+ size = pages * GRUB_EFI_PAGE_SIZE; |
|
|
|
prev_max = max; |
|
addr = grub_efi_allocate_pages_real (max, pages, |
|
max_addresses[i].alloc_type, |
|
memtype); |
|
if (addr) |
|
- grub_dprintf ("linux", "Allocated at %p\n", addr); |
|
+ { |
|
+ grub_dprintf ("linux", "Allocated at %p\n", addr); |
|
+ grub_update_mem_attrs ((grub_addr_t)addr, size, |
|
+ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, |
|
+ GRUB_MEM_ATTR_X); |
|
+ } |
|
} |
|
|
|
while (grub_error_pop ()) |
|
@@ -138,9 +144,11 @@ grub_linuxefi_boot (void *data) |
|
|
|
asm volatile ("cli"); |
|
|
|
- return grub_efi_linux_boot ((char *)context->kernel_mem, |
|
+ return grub_efi_linux_boot ((grub_addr_t)context->kernel_mem, |
|
+ context->kernel_size, |
|
context->handover_offset, |
|
- context->params); |
|
+ context->params, |
|
+ context->nx_supported); |
|
} |
|
|
|
static grub_err_t |
|
@@ -306,7 +314,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
grub_uint32_t handover_offset; |
|
struct linux_kernel_params *params = 0; |
|
char *cmdline = 0; |
|
+ int nx_supported = 1; |
|
struct grub_linuxefi_context *context = 0; |
|
+ grub_err_t err; |
|
|
|
grub_dl_ref (my_mod); |
|
|
|
@@ -347,6 +357,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
} |
|
} |
|
|
|
+ err = grub_efi_check_nx_image_support ((grub_addr_t)kernel, filelen, |
|
+ &nx_supported); |
|
+ if (err != GRUB_ERR_NONE) |
|
+ return err; |
|
+ grub_dprintf ("linux", "nx is%s supported by this kernel\n", |
|
+ nx_supported ? "" : " not"); |
|
+ |
|
lh = (struct linux_i386_kernel_header *)kernel; |
|
grub_dprintf ("linux", "original lh is at %p\n", kernel); |
|
|
|
@@ -511,6 +528,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
context->handover_offset = handover_offset; |
|
context->params = params; |
|
context->cmdline = cmdline; |
|
+ context->nx_supported = nx_supported; |
|
|
|
grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0); |
|
|
|
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c |
|
index 4aeb0e4b9a..3c1ff64763 100644 |
|
--- a/grub-core/loader/i386/linux.c |
|
+++ b/grub-core/loader/i386/linux.c |
|
@@ -805,6 +805,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
kernel_offset += len; |
|
} |
|
|
|
+ grub_dprintf("efi", "setting attributes for %p (%zu bytes) to +rw-x\n", |
|
+ &linux_params, sizeof (lh) + len); |
|
+ grub_update_mem_attrs ((grub_addr_t)&linux_params, sizeof (lh) + len, |
|
+ GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, GRUB_MEM_ATTR_X); |
|
+ |
|
linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR; |
|
linux_params.kernel_alignment = (1 << align); |
|
linux_params.ps_mouse = linux_params.padding11 = 0; |
|
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h |
|
index 34825c4adc..449e55269f 100644 |
|
--- a/include/grub/efi/efi.h |
|
+++ b/include/grub/efi/efi.h |
|
@@ -140,12 +140,16 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, |
|
char **device, |
|
char **path); |
|
|
|
+extern grub_addr_t EXPORT_VAR(grub_stack_addr); |
|
+extern grub_size_t EXPORT_VAR(grub_stack_size); |
|
+ |
|
#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) |
|
void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); |
|
grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); |
|
#include <grub/cpu/linux.h> |
|
grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh); |
|
-grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args); |
|
+grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size, |
|
+ char *args, int nx_enabled); |
|
#endif |
|
|
|
grub_addr_t grub_efi_section_addr (const char *section); |
|
diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h |
|
index 0033d9305a..8130b19590 100644 |
|
--- a/include/grub/efi/linux.h |
|
+++ b/include/grub/efi/linux.h |
|
@@ -22,10 +22,23 @@ |
|
#include <grub/err.h> |
|
#include <grub/symbol.h> |
|
|
|
+#define GRUB_MOK_POLICY_NX_REQUIRED 0x1 |
|
+ |
|
int |
|
EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size); |
|
+ |
|
grub_err_t |
|
-EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, |
|
- void *kernel_param); |
|
+EXPORT_FUNC(grub_efi_linux_boot) (grub_addr_t kernel_address, |
|
+ grub_size_t kernel_size, |
|
+ grub_off_t handover_offset, |
|
+ void *kernel_param, int nx_enabled); |
|
+ |
|
+grub_err_t |
|
+EXPORT_FUNC(grub_efi_check_nx_image_support) (grub_addr_t kernel_addr, |
|
+ grub_size_t kernel_size, |
|
+ int *nx_supported); |
|
+ |
|
+grub_err_t |
|
+EXPORT_FUNC(grub_efi_check_nx_required) (int *nx_required); |
|
|
|
#endif /* ! GRUB_EFI_LINUX_HEADER */ |
|
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h |
|
index 2a5e1ee003..a5e623eb04 100644 |
|
--- a/include/grub/efi/pe32.h |
|
+++ b/include/grub/efi/pe32.h |
|
@@ -181,6 +181,8 @@ struct grub_pe32_optional_header |
|
struct grub_pe32_data_directory reserved_entry; |
|
}; |
|
|
|
+#define GRUB_PE32_NX_COMPAT 0x0100 |
|
+ |
|
struct grub_pe64_optional_header |
|
{ |
|
grub_uint16_t magic;
|
|
|