• Matt Fleming's avatar
    x86/efi: Fix boot crash by mapping EFI memmap entries bottom-up at runtime, instead of top-down · 4a76b64a
    Matt Fleming authored
    commit a5caa209 upstream.
    
    Beginning with UEFI v2.5 EFI_PROPERTIES_TABLE was introduced
    that signals that the firmware PE/COFF loader supports splitting
    code and data sections of PE/COFF images into separate EFI
    memory map entries. This allows the kernel to map those regions
    with strict memory protections, e.g. EFI_MEMORY_RO for code,
    EFI_MEMORY_XP for data, etc.
    
    Unfortunately, an unwritten requirement of this new feature is
    that the regions need to be mapped with the same offsets
    relative to each other as observed in the EFI memory map. If
    this is not done crashes like this may occur,
    
      BUG: unable to handle kernel paging request at fffffffefe6086dd
      IP: [<fffffffefe6086dd>] 0xfffffffefe6086dd
      Call Trace:
       [<ffffffff8104c90e>] efi_call+0x7e/0x100
       [<ffffffff81602091>] ? virt_efi_set_variable+0x61/0x90
       [<ffffffff8104c583>] efi_delete_dummy_variable+0x63/0x70
       [<ffffffff81f4e4aa>] efi_enter_virtual_mode+0x383/0x392
       [<ffffffff81f37e1b>] start_kernel+0x38a/0x417
       [<ffffffff81f37495>] x86_64_start_reservations+0x2a/0x2c
       [<ffffffff81f37582>] x86_64_start_kernel+0xeb/0xef
    
    Here 0xfffffffefe6086dd refers to an address the firmware
    expects to be mapped but which the OS never claimed was mapped.
    The issue is that included in these regions are relative
    addresses to other regions which were emitted by the firmware
    toolchain before the "splitting" of sections occurred at
    runtime.
    
    Needless to say, we don't satisfy this unwritten requirement on
    x86_64 and instead map the EFI memory map entries in reverse
    order. The above crash is almost certainly triggerable with any
    kernel newer than v3.13 because that's when we rewrote the EFI
    runtime region mapping code, in commit d2f7cbe7 ("x86/efi:
    Runtime services virtual mapping"). For kernel versions before
    v3.13 things may work by pure luck depending on the
    fragmentation of the kernel virtual address space at the time we
    map the EFI regions.
    
    Instead of mapping the EFI memory map entries in reverse order,
    where entry N has a higher virtual address than entry N+1, map
    them in the same order as they appear in the EFI memory map to
    preserve this relative offset between regions.
    
    This patch has been kept as small as possible with the intention
    that it should be applied aggressively to stable and
    distribution kernels. It is very much a bugfix rather than
    support for a new feature, since when EFI_PROPERTIES_TABLE is
    enabled we must map things as outlined above to even boot - we
    have no way of asking the firmware not to split the code/data
    regions.
    
    In fact, this patch doesn't even make use of the more strict
    memory protections available in UEFI v2.5. That will come later.
    Suggested-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
    Reported-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
    Signed-off-by: default avatarMatt Fleming <matt.fleming@intel.com>
    Cc: Borislav Petkov <bp@suse.de>
    Cc: Chun-Yi <jlee@suse.com>
    Cc: Dave Young <dyoung@redhat.com>
    Cc: H. Peter Anvin <hpa@zytor.com>
    Cc: James Bottomley <JBottomley@Odin.com>
    Cc: Lee, Chun-Yi <jlee@suse.com>
    Cc: Leif Lindholm <leif.lindholm@linaro.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Matthew Garrett <mjg59@srcf.ucam.org>
    Cc: Mike Galbraith <efault@gmx.de>
    Cc: Peter Jones <pjones@redhat.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: linux-kernel@vger.kernel.org
    Link: http://lkml.kernel.org/r/1443218539-7610-2-git-send-email-matt@codeblueprint.co.ukSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
    Signed-off-by: default avatarKamal Mostafa <kamal@canonical.com>
    4a76b64a
efi.c 25.2 KB