Add the flag GRUB_MM_ADD_REGION_IN_RANGE for the grub memory
allocator for it to allocate memory only in a span of
DEFAULT_MAX_COMBINED_SIZE around where EFI loaded grub.

Signed-off-by: Adriano Cordova <adriano.cord...@canonical.com>
---
 grub-core/kern/efi/mm.c | 56 ++++++++++++++++++++++++++++++++++++++---
 include/grub/mm.h       |  1 +
 2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index df238b165..47cd297a5 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -41,6 +41,9 @@
 /* The default heap size for GRUB itself in bytes.  */
 #define DEFAULT_HEAP_SIZE      0x2000000
 
+/* The default combined size of image and allocated memory regions */
+#define DEFAULT_MAX_COMBINED_SIZE 0x80000000ULL  /* 2 GiB */
+
 static void *finish_mmap_buf = 0;
 static grub_efi_uintn_t finish_mmap_size = 0;
 static grub_efi_uintn_t finish_key = 0;
@@ -487,6 +490,38 @@ filter_memory_map (grub_efi_memory_descriptor_t 
*memory_map,
   return filtered_desc;
 }
 
+static grub_err_t
+check_range (grub_efi_physical_address_t region_start, grub_efi_uint64_t pages)
+{
+  grub_efi_loaded_image_t *image;
+  grub_efi_physical_address_t region_end;
+  grub_efi_physical_address_t range_start, range_end;
+  static grub_efi_physical_address_t image_start;
+  static grub_efi_physical_address_t image_end;
+
+  if (!image_start)
+  {
+    image = grub_efi_get_loaded_image (grub_efi_image_handle);
+    if (!image)
+      return 0;
+    image_start = (grub_efi_physical_address_t) (grub_addr_t) 
image->image_base;
+    image_end = image_start + image->image_size;
+  }
+
+  region_end = region_start + PAGES_TO_BYTES(pages);
+
+  range_start = (image_start < region_start) ? image_start : region_start;
+  range_end = (image_end > region_end) ? image_end : region_end;
+
+  if ((range_end - range_start) > DEFAULT_MAX_COMBINED_SIZE)
+    return GRUB_ERR_OUT_OF_MEMORY;
+
+  image_start = range_start;
+  image_end = range_end;
+
+  return GRUB_ERR_NONE;
+}
+
 /* Add memory regions.  */
 static grub_err_t
 add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
@@ -496,6 +531,7 @@ add_memory_regions (grub_efi_memory_descriptor_t 
*memory_map,
                    unsigned int flags)
 {
   grub_efi_memory_descriptor_t *desc;
+  grub_err_t err;
 
   for (desc = memory_map;
        desc < memory_map_end;
@@ -512,10 +548,22 @@ add_memory_regions (grub_efi_memory_descriptor_t 
*memory_map,
        continue;
 
       if (pages > required_pages)
-       {
-         start += PAGES_TO_BYTES (pages - required_pages);
-         pages = required_pages;
-       }
+      {
+        start += PAGES_TO_BYTES (pages - required_pages);
+        if ((flags & GRUB_MM_ADD_REGION_IN_RANGE) && check_range(start, 
required_pages))
+          {
+            start -= PAGES_TO_BYTES (pages - required_pages);
+            err = check_range(start, required_pages);
+          }
+        pages = required_pages;
+      } else {
+        if ((flags & GRUB_MM_ADD_REGION_IN_RANGE))
+          err = check_range(start, required_pages);
+      }
+
+      if (err != GRUB_ERR_NONE)
+        return err;
+
 
       addr = grub_efi_allocate_pages_real (start, pages,
                                           GRUB_EFI_ALLOCATE_ADDRESS,
diff --git a/include/grub/mm.h b/include/grub/mm.h
index 51ec0b8f9..9a0c99b99 100644
--- a/include/grub/mm.h
+++ b/include/grub/mm.h
@@ -31,6 +31,7 @@
 
 #define GRUB_MM_ADD_REGION_NONE        0
 #define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0)
+#define GRUB_MM_ADD_REGION_IN_RANGE (1 << 1)
 
 /*
  * Function used to request memory regions of `grub_size_t` bytes. The second
-- 
2.48.1


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

Reply via email to