mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 09:14:19 +08:00
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: Borislav Petkov <bp@suse.de> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
parent
568035b01c
commit
6c3a9c9ae0
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user