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