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.prak...@intel.com>
Suggested-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Borislav Petkov <b...@alien8.de>
Cc: Bhupesh Sharma <bhsha...@redhat.com>
Cc: Ard Biesheuvel <ard.biesheu...@linaro.org>

-- 
2.19.1

Reply via email to