mirror of
https://git.savannah.gnu.org/git/grub.git
synced 2026-10-21 14:59:34 +00:00
kern/efi/mm: Change grub_efi_mm_add_regions() to keep track of map allocation size
If the map was too big for the initial allocation, it was freed and replaced with a bigger one, but the free call still used the hard-coded size. Seems like this wasn't hit for a long time, because most firmware maps fit into 12K. This bug was triggered on Project Mu firmware with a big memory map, and results in the heap getting trashed and the firmware ASSERTING on corrupted heap guard values when GRUB exits. Signed-off-by: Mate Kukri <mate.kukri@canonical.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
1 parent
b990df0bef
commit
dc0a3a27d6
1 file changed
+7
-7
@@ -574,13 +574,15 @@ grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags)
|
|||||||
grub_efi_memory_descriptor_t *memory_map_end;
|
grub_efi_memory_descriptor_t *memory_map_end;
|
||||||
grub_efi_memory_descriptor_t *filtered_memory_map;
|
grub_efi_memory_descriptor_t *filtered_memory_map;
|
||||||
grub_efi_memory_descriptor_t *filtered_memory_map_end;
|
grub_efi_memory_descriptor_t *filtered_memory_map_end;
|
||||||
|
grub_efi_uintn_t alloc_size;
|
||||||
grub_efi_uintn_t map_size;
|
grub_efi_uintn_t map_size;
|
||||||
grub_efi_uintn_t desc_size;
|
grub_efi_uintn_t desc_size;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
int mm_status;
|
int mm_status;
|
||||||
|
|
||||||
/* Prepare a memory region to store two memory maps. */
|
/* Prepare a memory region to store two memory maps. */
|
||||||
memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
|
alloc_size = 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE);
|
||||||
|
memory_map = grub_efi_allocate_any_pages (alloc_size);
|
||||||
if (! memory_map)
|
if (! memory_map)
|
||||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map");
|
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map");
|
||||||
|
|
||||||
@@ -591,14 +593,13 @@ grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags)
|
|||||||
|
|
||||||
if (mm_status == 0)
|
if (mm_status == 0)
|
||||||
{
|
{
|
||||||
grub_efi_free_pages
|
grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) memory_map, alloc_size);
|
||||||
((grub_efi_physical_address_t) ((grub_addr_t) memory_map),
|
|
||||||
2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
|
|
||||||
|
|
||||||
/* Freeing/allocating operations may increase memory map size. */
|
/* Freeing/allocating operations may increase memory map size. */
|
||||||
map_size += desc_size * 32;
|
map_size += desc_size * 32;
|
||||||
|
|
||||||
memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size));
|
alloc_size = 2 * BYTES_TO_PAGES (map_size);
|
||||||
|
memory_map = grub_efi_allocate_any_pages (alloc_size);
|
||||||
if (! memory_map)
|
if (! memory_map)
|
||||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map");
|
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map");
|
||||||
|
|
||||||
@@ -642,8 +643,7 @@ grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Release the memory maps. */
|
/* Release the memory maps. */
|
||||||
grub_efi_free_pages ((grub_addr_t) memory_map,
|
grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) memory_map, alloc_size);
|
||||||
2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user