]> git.baikalelectronics.ru Git - kernel.git/commitdiff
efi/x86-mixed: move unmitigated RET into .rodata
authorArd Biesheuvel <ardb@kernel.org>
Fri, 22 Jul 2022 15:15:41 +0000 (17:15 +0200)
committerArd Biesheuvel <ardb@kernel.org>
Tue, 16 Aug 2022 07:28:05 +0000 (09:28 +0200)
Move the EFI mixed mode return trampoline RET into .rodata, so it is
normally mapped without executable permissions.  And given that this
snippet of code is really the only kernel code that we ever execute via
this 1:1 mapping, let's unmap the 1:1 mapping of the kernel .text, and
only map the page that covers the return trampoline with executable
permissions.

Note that the remainder of .rodata needs to remain mapped into the 1:1
mapping with RO/NX permissions, as literal GUIDs and strings may be
passed to the variable routines.

Acked-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
arch/x86/platform/efi/efi_64.c
arch/x86/platform/efi/efi_thunk_64.S

index 1f3675453a57ab61bbae2f1074135246c8559fa0..b36596bf0fc38f4fbf907f5c19147425a2a4360d 100644 (file)
@@ -176,7 +176,8 @@ virt_to_phys_or_null_size(void *va, unsigned long size)
 
 int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
-       unsigned long pfn, text, pf, rodata;
+       extern const u8 __efi64_thunk_ret_tramp[];
+       unsigned long pfn, text, pf, rodata, tramp;
        struct page *page;
        unsigned npages;
        pgd_t *pgd = efi_mm.pgd;
@@ -238,11 +239,9 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 
        npages = (_etext - _text) >> PAGE_SHIFT;
        text = __pa(_text);
-       pfn = text >> PAGE_SHIFT;
 
-       pf = _PAGE_ENC;
-       if (kernel_map_pages_in_pgd(pgd, pfn, text, npages, pf)) {
-               pr_err("Failed to map kernel text 1:1\n");
+       if (kernel_unmap_pages_in_pgd(pgd, text, npages)) {
+               pr_err("Failed to unmap kernel text 1:1 mapping\n");
                return 1;
        }
 
@@ -256,6 +255,15 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
                return 1;
        }
 
+       tramp = __pa(__efi64_thunk_ret_tramp);
+       pfn = tramp >> PAGE_SHIFT;
+
+       pf = _PAGE_ENC;
+       if (kernel_map_pages_in_pgd(pgd, pfn, tramp, 1, pf)) {
+               pr_err("Failed to map mixed mode return trampoline\n");
+               return 1;
+       }
+
        return 0;
 }
 
index 4e5257a4811b28e980b9bd48f813be1448154273..c4b1144f99f6362aa4ac56a3eedc355c9722cb04 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/objtool.h>
 #include <asm/page_types.h>
 #include <asm/segment.h>
-#include <asm/nospec-branch.h>
 
        .text
        .code64
@@ -73,10 +72,18 @@ STACK_FRAME_NON_STANDARD __efi64_thunk
        pushq   %rdi                    /* EFI runtime service address */
        lretq
 
+       // This return instruction is not needed for correctness, as it will
+       // never be reached. It only exists to make objtool happy, which will
+       // otherwise complain about unreachable instructions in the callers.
+       RET
+SYM_FUNC_END(__efi64_thunk)
+
+       .section ".rodata", "a", @progbits
+       .balign 16
+SYM_DATA_START(__efi64_thunk_ret_tramp)
 1:     movq    0x20(%rsp), %rsp
        pop     %rbx
        pop     %rbp
-       ANNOTATE_UNRET_SAFE
        ret
        int3
 
@@ -84,7 +91,7 @@ STACK_FRAME_NON_STANDARD __efi64_thunk
 2:     pushl   $__KERNEL_CS
        pushl   %ebp
        lret
-SYM_FUNC_END(__efi64_thunk)
+SYM_DATA_END(__efi64_thunk_ret_tramp)
 
        .bss
        .balign 8