Re: [PATCH RFC 0/8] Add efi page fault handler to fix/recover from

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



(+ Ingo, Andy, Peter)

Hello Sai,

I have added some x86/intel folks to cc.

I am fine with these patches, and I think it is useful to be able to
detect and recover from buggy UEFI implementations that use boot time
regions at runtime.

However, I need help from the x86 maintainers/developers to review
this so please cc them on these patches.

Thanks,
Ard.

On 22 July 2018 at 07:41, Sai Praneeth Prakhya
<sai.praneeth.prakhya@xxxxxxxxx> wrote:
> From: Sai Praneeth <sai.praneeth.prakhya@xxxxxxxxx>
>
> There may exist some buggy UEFI firmware implementations that access efi
> memory regions other than EFI_RUNTIME_SERVICES_<CODE/DATA> even after
> kernel has assumed control of the platform. This violates UEFI
> specification. Here, we provide a debug config option which when enabled
> detects and fixes up/recovers from page faults caused by buggy firmware.
>
> The above said illegal accesses trigger page fault in ring 0 because
> firmware executes at ring 0 and if unhandled it hangs the kernel. We
> provide an efi specific page fault handler to:
> 1. Avoid panics/hangs caused by buggy firmware.
> 2. Shout loud that the firmware is buggy and hence can save ourselves
> from being blamed for not a fault of ours.
>
> Depending on the illegally accessed efi region, the efi page fault
> handler handles illegal accesses differently.
> 1. If the illegally accessed region is EFI_BOOT_SERVICES_<CODE/DATA>,
> the page fault handler fixes it up by mapping the requested region.
> 2. If the illegally accessed region is any other efi region (like
> EFI_CONVENTIONAL_MEMORY or EFI_LOADER_<CODE/DATA>), the page fault
> handler exits firmware context and disables EFI Runtime Services, so
> that we will never again call buggy firmware.
>
> Page faults to efi regions are handled differently because, presently
> during kernel boot, EFI_BOOT_SERVICES_<CODE/DATA> regions are reserved
> by kernel and hence it's OK to dynamically map these regions in page
> fault handler. The same approach cannot be followed for other efi
> regions like EFI_CONVENTIONAL_MEMORY and EFI_LOADER_<CODE/DATA> as they
> are very huge in size and reserving them could make the kernel
> un-bootable. Hence, we take a different approach (exiting firmware
> context) while dealing with page faults to these regions. This also
> saves us from executing buggy firmware further.
>
> Exiting firmware context means that on every entry to firmware we save
> the kernel context before calling firmware and if the firmware
> misbehaves, in the page fault handler, we roll back to the saved kernel
> context. Saving kernel context means saving the stack pointer and the
> instruction that gets executed when firmware returns. In the page fault
> handler we fix up these two things (RIP and RSP) so that when returning
> from page fault handler it looks as if firmware has called RET.
>
> This issue was reported by Al Stone when he saw that reboot via EFI hangs
> the machine. Upon debugging, I found that it's efi_reset_system() that's
> touching memory regions which it shouldn't. To reproduce the same
> behavior, I have hacked OVMF and made efi_reset_system() buggy.
>
> Testing the patch set:
> ----------------------
> 1. Download buggy firmware from here [1].
> 2. Run a qemu instance with this buggy BIOS and boot mainline kernel.
> Add reboot=efi to the kernel command line arguments and after the kernel
> is up and running, type "reboot". The kernel should hang while rebooting.
> 3. With the same setup, boot kernel after applying patches and the
> reboot should work fine. Also please notice warning/error messages
> printed by kernel.
>
> Note:
> -----
> Patch set based on "next" branch in efi tree.
>
> [1] https://drive.google.com/open?id=1tkvT7GaVX2zSlzy1HK1T4Tv8cT36GP6R
>
> Sai Praneeth (8):
>   x86/efi: Remove __init attribute from memory mapping functions
>   x86/efi: Permanently save the EFI_MEMORY_MAP passed by firmware
>   x86/efi: Save kernel context before calling EFI Runtime Services
>   x86/efi: Add page fault handler to fixup/recover from page faults
>     caused by firmware
>   x86/efi: If EFI_WARN_ON_ILLEGAL_ACCESSES is enabled don't call
>     efi_free_boot_services()
>   x86/efi: Map EFI_BOOT_SERVICES_<CODE/DATA> regions only when
>     EFI_WARN_ON_ILLEGAL_ACCESSES is disabled
>   x86/mm: If in_atomic(), allocate pages without sleeping
>   x86/efi: Introduce EFI_WARN_ON_ILLEGAL_ACCESSES
>
>  arch/x86/Kconfig                        |  17 +++
>  arch/x86/include/asm/efi.h              |  42 ++++++-
>  arch/x86/mm/fault.c                     |   9 ++
>  arch/x86/mm/pageattr.c                  |  16 ++-
>  arch/x86/platform/efi/efi.c             |  10 +-
>  arch/x86/platform/efi/efi_32.c          |   2 +-
>  arch/x86/platform/efi/efi_64.c          |  16 ++-
>  arch/x86/platform/efi/efi_stub_64.S     | 101 ++++++++++++++++-
>  arch/x86/platform/efi/quirks.c          | 193 ++++++++++++++++++++++++++++++++
>  drivers/firmware/efi/efi.c              |   6 +-
>  drivers/firmware/efi/runtime-wrappers.c |   6 +
>  include/linux/efi.h                     |  16 ++-
>  init/main.c                             |   3 +-
>  13 files changed, 415 insertions(+), 22 deletions(-)
>
> Signed-off-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@xxxxxxxxx>
> Suggested-by: Matt Fleming <matt@xxxxxxxxxxxxxxxxxxx>
> Based-on-code-from: Ricardo Neri <ricardo.neri@xxxxxxxxx>
> Cc: Al Stone <astone@xxxxxxxxxx>
> Cc: Lee Chun-Yi <jlee@xxxxxxxx>
> Cc: Borislav Petkov <bp@xxxxxxxxx>
> Cc: Bhupesh Sharma <bhsharma@xxxxxxxxxx>
> Cc: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx>
>
> --
> 2.7.4
>
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux