The UEFI specification states that the firmware shall not access the
BOOT_SERVICES_DATA/CODE * memory regions after the operating system has
called ExitBootServices on it. Thus, the operating system is free to use
such regions as it sees fit. Still, buggy UEFI firmware implementations
may want to keep accessing these regions.

The current approach of the kernel is to reserve and map the
EFI_BOOT_SERVICES_* regions until efi_free_boot_services() is called
(after calling SetVirtualAddressMap() on the firmware). Further details
are show in the commit 916f676f8dc0 ("x86, efi: Retain boot service code
until after switching to virtual mode") by Matthew Garrett.

A drawback of the current approach is that silently working around this
kind of illegal accesses encourages the perpetuation of these bugs in
UEFI firmware implementations. Rather, this set of patches proposes a
more verbose behavior: continue reserving the EFI_BOOT_SERVICES_* regions
but not map them. If they are not mapped, any access will cause a page
fault that we can catch. Once the fault is catched, the kernel will fix
it up (i.e., map the page for the firmware to use it) and, more important,
complain about it.

We are guaranteed to not have false positives (i.e., page faults caused
by bad kernel code) as these memory regions are still reserved.

Besides fixing up the illegal accesses, no further action is required to
update the memory map the firmware sees. This is true because after boot,
the firmware would require access to the runtime services memory only,
which should be mapped before calling SetVirtualAddressMap. Furthermore,
a second attempt to update the virtual address map will result in a
EFI_UNSUPPORTED from the firmware, as per the UEFI specification.

Also, there is no need to update the system table as it should have been
when mapping the rest of the memory regions.

Finally, kexec is concerned only about the runtime services memory
sections. Thus we don't need any special arrangements for kexec.

The four last patches of the set implement this approach. The first two
provide a rework for code reuse of the convenience functions that look
for the descriptor of a physical memory address when then be used by the
proposed solution.

Ricardo Neri (6):
  x86/efi: Add function to obtain mem descriptor from phys address
  x86/efi: Use efi_memory_descriptor in mem convenience functions
  x86/efi: Add function to fixup page faults in BOOT_SERVICES_* regions
  x86/efi: Remove __init attribute from memory mapping functions
  yx86/efi: Fixup faults from UEFI firmware
  x86/efi: Introduce EFI_BOOT_SERVICES_WARN

 arch/x86/Kconfig               | 12 ++++++++
 arch/x86/include/asm/efi.h     |  4 +--
 arch/x86/mm/fault.c            |  8 +++++
 arch/x86/platform/efi/efi.c    | 66 ++++++++++++++++++++++++++++++++----------
 arch/x86/platform/efi/efi_32.c |  2 +-
 arch/x86/platform/efi/efi_64.c |  8 ++---
 drivers/firmware/efi/efi.c     | 36 ++++++++++-------------
 include/linux/efi.h            |  9 ++++++
 8 files changed, 101 insertions(+), 44 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to