Commit 6c3a9c9a authored by Ard Biesheuvel's avatar Ard Biesheuvel

efi/x86-mixed: move unmitigated RET into .rodata

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: default avatarBorislav Petkov <bp@suse.de>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent 568035b0
...@@ -176,7 +176,8 @@ virt_to_phys_or_null_size(void *va, unsigned long size) ...@@ -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) 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; struct page *page;
unsigned npages; unsigned npages;
pgd_t *pgd = efi_mm.pgd; pgd_t *pgd = efi_mm.pgd;
...@@ -238,11 +239,9 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) ...@@ -238,11 +239,9 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
npages = (_etext - _text) >> PAGE_SHIFT; npages = (_etext - _text) >> PAGE_SHIFT;
text = __pa(_text); text = __pa(_text);
pfn = text >> PAGE_SHIFT;
pf = _PAGE_ENC; if (kernel_unmap_pages_in_pgd(pgd, text, npages)) {
if (kernel_map_pages_in_pgd(pgd, pfn, text, npages, pf)) { pr_err("Failed to unmap kernel text 1:1 mapping\n");
pr_err("Failed to map kernel text 1:1\n");
return 1; return 1;
} }
...@@ -256,6 +255,15 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) ...@@ -256,6 +255,15 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
return 1; 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; return 0;
} }
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/objtool.h> #include <linux/objtool.h>
#include <asm/page_types.h> #include <asm/page_types.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/nospec-branch.h>
.text .text
.code64 .code64
...@@ -73,10 +72,18 @@ STACK_FRAME_NON_STANDARD __efi64_thunk ...@@ -73,10 +72,18 @@ STACK_FRAME_NON_STANDARD __efi64_thunk
pushq %rdi /* EFI runtime service address */ pushq %rdi /* EFI runtime service address */
lretq 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 1: movq 0x20(%rsp), %rsp
pop %rbx pop %rbx
pop %rbp pop %rbp
ANNOTATE_UNRET_SAFE
ret ret
int3 int3
...@@ -84,7 +91,7 @@ STACK_FRAME_NON_STANDARD __efi64_thunk ...@@ -84,7 +91,7 @@ STACK_FRAME_NON_STANDARD __efi64_thunk
2: pushl $__KERNEL_CS 2: pushl $__KERNEL_CS
pushl %ebp pushl %ebp
lret lret
SYM_FUNC_END(__efi64_thunk) SYM_DATA_END(__efi64_thunk_ret_tramp)
.bss .bss
.balign 8 .balign 8
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment