When running with return thunks enabled under 32-bit EFI, the system
crashes with:
kernel tried to execute NX-protected page - exploit attempt? (uid: 0)
BUG: unable to handle page fault for address: 000000005bc02900
#PF: supervisor instruction fetch in kernel mode
#PF: error_code(0x0011) - permissions violation
PGD 18f7063 P4D 18f7063 PUD 18ff063 PMD 190e063 PTE 800000005bc02063
Oops: 0011 [#1] PREEMPT SMP PTI
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.19.0-rc6+ #166
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
RIP: 0010:0x5bc02900
Code: Unable to access opcode bytes at RIP 0x5bc028d6.
RSP: 0018:ffffffffb3203e10 EFLAGS: 00010046
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000048
RDX: 000000000190dfac RSI: 0000000000001710 RDI: 000000007eae823b
RBP: ffffffffb3203e70 R08: 0000000001970000 R09: ffffffffb3203e28
R10: 747563657865206c R11: 6c6977203a696665 R12: 0000000000001710
R13: 0000000000000030 R14: 0000000001970000 R15: 0000000000000001
FS: 0000000000000000(0000) GS:ffff8e013ca00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0018 ES: 0018 CR0: 0000000080050033
CR2: 000000005bc02900 CR3: 0000000001930000 CR4: 00000000000006f0
Call Trace:
? efi_set_virtual_address_map+0x9c/0x175
efi_enter_virtual_mode+0x4a6/0x53e
start_kernel+0x67c/0x71e
x86_64_start_reservations+0x24/0x2a
x86_64_start_kernel+0xe9/0xf4
secondary_startup_64_no_verify+0xe5/0xeb
That's because it cannot jump to the return thunk from the 32-bit code.
Using a naked RET and marking it as safe allows the system to proceed
booting.
Fixes: aa3d480315
("x86: Use return-thunk in asm code")
Reported-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: <stable@vger.kernel.org>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
91 lines
2.1 KiB
ArmAsm
91 lines
2.1 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (C) 2014 Intel Corporation; author Matt Fleming
|
|
*
|
|
* Support for invoking 32-bit EFI runtime services from a 64-bit
|
|
* kernel.
|
|
*
|
|
* The below thunking functions are only used after ExitBootServices()
|
|
* has been called. This simplifies things considerably as compared with
|
|
* the early EFI thunking because we can leave all the kernel state
|
|
* intact (GDT, IDT, etc) and simply invoke the 32-bit EFI runtime
|
|
* services from __KERNEL32_CS. This means we can continue to service
|
|
* interrupts across an EFI mixed mode call.
|
|
*
|
|
* We do however, need to handle the fact that we're running in a full
|
|
* 64-bit virtual address space. Things like the stack and instruction
|
|
* addresses need to be accessible by the 32-bit firmware, so we rely on
|
|
* using the identity mappings in the EFI page table to access the stack
|
|
* and kernel text (see efi_setup_page_tables()).
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <linux/objtool.h>
|
|
#include <asm/page_types.h>
|
|
#include <asm/segment.h>
|
|
#include <asm/nospec-branch.h>
|
|
|
|
.text
|
|
.code64
|
|
SYM_FUNC_START(__efi64_thunk)
|
|
STACK_FRAME_NON_STANDARD __efi64_thunk
|
|
push %rbp
|
|
push %rbx
|
|
|
|
/*
|
|
* Switch to 1:1 mapped 32-bit stack pointer.
|
|
*/
|
|
movq %rsp, %rax
|
|
movq efi_mixed_mode_stack_pa(%rip), %rsp
|
|
push %rax
|
|
|
|
/*
|
|
* Copy args passed via the stack
|
|
*/
|
|
subq $0x24, %rsp
|
|
movq 0x18(%rax), %rbp
|
|
movq 0x20(%rax), %rbx
|
|
movq 0x28(%rax), %rax
|
|
movl %ebp, 0x18(%rsp)
|
|
movl %ebx, 0x1c(%rsp)
|
|
movl %eax, 0x20(%rsp)
|
|
|
|
/*
|
|
* Calculate the physical address of the kernel text.
|
|
*/
|
|
movq $__START_KERNEL_map, %rax
|
|
subq phys_base(%rip), %rax
|
|
|
|
leaq 1f(%rip), %rbp
|
|
leaq 2f(%rip), %rbx
|
|
subq %rax, %rbp
|
|
subq %rax, %rbx
|
|
|
|
movl %ebx, 0x0(%rsp) /* return address */
|
|
movl %esi, 0x4(%rsp)
|
|
movl %edx, 0x8(%rsp)
|
|
movl %ecx, 0xc(%rsp)
|
|
movl %r8d, 0x10(%rsp)
|
|
movl %r9d, 0x14(%rsp)
|
|
|
|
/* Switch to 32-bit descriptor */
|
|
pushq $__KERNEL32_CS
|
|
pushq %rdi /* EFI runtime service address */
|
|
lretq
|
|
|
|
1: movq 0x20(%rsp), %rsp
|
|
pop %rbx
|
|
pop %rbp
|
|
ANNOTATE_UNRET_SAFE
|
|
ret
|
|
int3
|
|
|
|
.code32
|
|
2: pushl $__KERNEL_CS
|
|
pushl %ebp
|
|
lret
|
|
SYM_FUNC_END(__efi64_thunk)
|
|
|
|
.bss
|
|
.balign 8
|
|
SYM_DATA(efi_mixed_mode_stack_pa, .quad 0)
|