grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH RFC 3/3] efi: explicitly set memory attributes for memory


From: Baskov Evgeniy
Subject: [PATCH RFC 3/3] efi: explicitly set memory attributes for memory
Date: Thu, 7 Apr 2022 06:32:28 +0300

UEFI specification does not guarantee that memory
used for trampoline by GRUB would be executable.
Some stricter implementations set NX flag for most
regions.

Explicitly mark memory range where trampoline would
be allocated as writable and executable
using DXE services on x86-efi variations.

Avoid modification if not necessary and only modify
system memory to reduce the possibility to encounter
firmware bugs.

Signed-off-by: Baskov Evgeniy <baskov@ispras.ru>

diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index d8e411454..f6d1170d1 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -230,6 +230,71 @@ stop_broadcom (void)
 
 #endif
 
+static void
+unprotect_memory_range (grub_efi_physical_address_t start,
+                        grub_efi_physical_address_t end)
+{
+  static grub_efi_guid_t dxe_guid = GRUB_EFI_DXE_SERVICES_TABLE_GUID;
+  grub_efi_physical_address_t rounded_start, rounded_end, next;
+  grub_efi_physical_address_t unprotect_start, unprotect_end;
+  grub_efi_dxe_services_t *dxe;
+  grub_efi_gcd_memory_space_descriptor_t desc;
+  grub_efi_status_t status;
+
+  dxe = grub_efi_get_config_table (&dxe_guid);
+  if (dxe == NULL || dxe->hdr.signature != GRUB_EFI_DXE_SERVICES_SIGNATURE)
+    return;
+
+  rounded_start = start & ~GRUB_EFI_PAGE_SIZE;
+  rounded_end = (end + GRUB_EFI_PAGE_SIZE - 1) & ~GRUB_EFI_PAGE_SIZE;
+
+  /*
+   * Don't modify memory region attributes, they are
+   * already suitable, to lower the possibility to
+   * encounter firmware bugs.
+   */
+
+  for (; start < end; start = next)
+    {
+      status = efi_call_2 (dxe->get_memory_space_descriptor, start, &desc);
+
+      if (status != GRUB_EFI_SUCCESS)
+        return;
+
+      next = desc.base_address + desc.length;
+
+      /*
+       * Only system memory is suitable for trampoline/kernel image placement,
+       * so only this type of memory needs its attributes to be modified.
+       */
+
+      if (desc.gcd_memory_type != GRUB_EFI_GCD_MEMORY_TYPE_SYSTEM_MEMORY ||
+          (desc.attributes & (GRUB_EFI_MEMORY_RO | GRUB_EFI_MEMORY_XP)) == 0)
+        continue;
+
+      unprotect_start = rounded_start;
+      if (unprotect_start < desc.base_address)
+        unprotect_start = desc.base_address;
+
+      unprotect_end = rounded_end;
+      if (unprotect_end > next)
+        unprotect_end = next;
+
+      status = efi_call_3 (dxe->set_memory_space_attributes,
+                          unprotect_start,
+                          unprotect_end - unprotect_start,
+                          GRUB_EFI_MEMORY_WB);
+
+      if (status != GRUB_EFI_SUCCESS)
+       {
+          grub_printf ("Cannot change memory attributes in range [0x%lX, 
0x%lX): 0x%lX\n",
+                      (long)unprotect_start,
+                      (long)unprotect_end,
+                      (long)status);
+       }
+    }
+}
+
 grub_err_t
 grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf,
                               grub_efi_uintn_t *map_key,
@@ -239,6 +304,8 @@ grub_efi_finish_boot_services (grub_efi_uintn_t 
*outbuf_size, void *outbuf,
   grub_efi_boot_services_t *b;
   grub_efi_status_t status;
 
+  unprotect_memory_range(0x1000, 0xa0000);
+
 #if defined (__i386__) || defined (__x86_64__)
   const grub_uint16_t apple[] = { 'A', 'p', 'p', 'l', 'e' };
   int is_apple;
-- 
2.35.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]