Presently, in EFI subsystem of kernel, every time kernel allocates memory for a new EFI memory map, it forgets to free the memory occupied by old EFI memory map. It does clear the mappings though (using efi_memmap_unmap()), but forgets to free up the memory. Also, there is another minor issue, where in the newly allocated memory isn't freed, should remap fail. The first issue is addressed by adding efi_memmap_free() to efi_memmap_install() and the second issue is addressed by pushing the remap code into efi_memmap_alloc() and there by handling the failure condition. Memory allocated to EFI memory map is leaked in below functions and hence they are modified to fix the issue. Functions that modify EFI memmap are: 1. efi_clean_memmap(), 2. efi_fake_memmap(), 3. efi_arch_mem_reserve(), 4. efi_free_boot_services(), 5. and __efi_enter_virtual_mode() More detailed explanation: -------------------------- A typical boot flow on EFI supported x86_64 machines might look something like below 1. EFI memory map is passed by firmware to kernel. 2. Kernel does a memblock_reserve() on this memory (see efi_memblock_x86_reserve_range()). 3. This memory map is checked for invalid entries in efi_clean_memmap(). If any invalid entries are found, they are omitted from EFI memory map but the memory occupied by these invalid EFI memory descriptors isn't freed. 3. To further process this memory map (see efi_fake_memmap(), efi_bgrt_init() and efi_esrt_init()), kernel allocates memory using efi_memmap_alloc() and copies the processed memory map to newly allocated memory but it forgets to free memory occupied by old EFI memory map. 4. Further, in efi_map_regions() the EFI memory map is processed again to include only EFI memory descriptors of type Runtime Code/Data and Boot Code/Data. Again, memory is allocated for this new memory map through realloc_pages() and the old EFI memory map is not freed. 5. After SetVirtualAddressMap() is done, the EFI memory map is processed again to have only EFI memory descriptors of type Runtime Code/Data. Again, memory is allocated for this new memory map through efi_memmap_alloc() and the old EFI memory map is not freed. Testing: -------- Tested with LUV on qemu-x86_64 and on my dev machine. Checked for unchanged boot behavior i.e. shouldn't break any existing stuff. Built for arm, arm64 and ia64 and found no new warnings/errors. Would appreciate the effort if someone could test on arm machines. Although majority of the changes are made to drivers/firmware/efi/memmap.c file (which is common across architectures), this bug is only limited to x86_64 machines and hence this patch set shouldn't effect any other architectures. Notes: ------ 1. This patch set is based on EFI tree's "next" branch [1]. 2. This patch set is an outcome of the discussion at [2]. Changes from V1: ---------------- 1. Drop passing around allocation type from efi_memmap_alloc(), instead change efi_memmap_alloc() such that it now returns a populated struct efi_memory_map 2. Drop fixing issues in efi_fake_memmap(), will be addressed in a separate patch. 3. Optimize efi_map_regions(). [1] git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git [2] https://lkml.org/lkml/2018/7/2/1095 Sai Praneeth Prakhya (3): efi: Introduce efi_memmap_free() and efi_memmap_unmap_and_free() x86/efi: Fix EFI memory map leaks x86/efi: Use efi_memmap_<alloc/install>() to create runtime EFI memory map arch/x86/include/asm/efi.h | 3 +- arch/x86/kernel/setup.c | 6 + arch/x86/platform/efi/efi.c | 141 +++++++++--------------- arch/x86/platform/efi/efi_32.c | 2 +- arch/x86/platform/efi/efi_64.c | 7 +- arch/x86/platform/efi/quirks.c | 45 ++------ drivers/firmware/efi/arm-init.c | 2 +- drivers/firmware/efi/fake_mem.c | 21 +--- drivers/firmware/efi/memmap.c | 190 +++++++++++++++++++++++++------- include/linux/efi.h | 8 +- 10 files changed, 235 insertions(+), 190 deletions(-) Signed-off-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@xxxxxxxxx> Suggested-by: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxxxxx> Cc: Borislav Petkov <bp@xxxxxxxxx> Cc: Bhupesh Sharma <bhsharma@xxxxxxxxxx> Cc: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> -- 2.19.1