Skip to content

Commit 3e3b929

Browse files
amlutoIngo Molnar
authored andcommitted
x86/entry/64: Return to userspace from the trampoline stack
By itself, this is useless. It gives us the ability to run some final code before exit that cannnot run on the kernel stack. This could include a CR3 switch a la PAGE_TABLE_ISOLATION or some kernel stack erasing, for example. (Or even weird things like *changing* which kernel stack gets used as an ASLR-strengthening mechanism.) The SYSRET32 path is not covered yet. It could be in the future or we could just ignore it and force the slow path if needed. Signed-off-by: Andy Lutomirski <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Thomas Gleixner <[email protected]> Reviewed-by: Borislav Petkov <[email protected]> Cc: Boris Ostrovsky <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Brian Gerst <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Dave Hansen <[email protected]> Cc: David Laight <[email protected]> Cc: Denys Vlasenko <[email protected]> Cc: Eduardo Valentin <[email protected]> Cc: Greg KH <[email protected]> Cc: H. Peter Anvin <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: Juergen Gross <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Rik van Riel <[email protected]> Cc: Will Deacon <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 7f2590a commit 3e3b929

File tree

1 file changed

+51
-4
lines changed

1 file changed

+51
-4
lines changed

arch/x86/entry/entry_64.S

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,24 @@ syscall_return_via_sysret:
326326
popq %rsi /* skip rcx */
327327
popq %rdx
328328
popq %rsi
329+
330+
/*
331+
* Now all regs are restored except RSP and RDI.
332+
* Save old stack pointer and switch to trampoline stack.
333+
*/
334+
movq %rsp, %rdi
335+
movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
336+
337+
pushq RSP-RDI(%rdi) /* RSP */
338+
pushq (%rdi) /* RDI */
339+
340+
/*
341+
* We are on the trampoline stack. All regs except RDI are live.
342+
* We can do future final exit work right here.
343+
*/
344+
329345
popq %rdi
330-
movq RSP-ORIG_RAX(%rsp), %rsp
346+
popq %rsp
331347
USERGS_SYSRET64
332348
END(entry_SYSCALL_64)
333349

@@ -630,10 +646,41 @@ GLOBAL(swapgs_restore_regs_and_return_to_usermode)
630646
ud2
631647
1:
632648
#endif
633-
SWAPGS
634649
POP_EXTRA_REGS
635-
POP_C_REGS
636-
addq $8, %rsp /* skip regs->orig_ax */
650+
popq %r11
651+
popq %r10
652+
popq %r9
653+
popq %r8
654+
popq %rax
655+
popq %rcx
656+
popq %rdx
657+
popq %rsi
658+
659+
/*
660+
* The stack is now user RDI, orig_ax, RIP, CS, EFLAGS, RSP, SS.
661+
* Save old stack pointer and switch to trampoline stack.
662+
*/
663+
movq %rsp, %rdi
664+
movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
665+
666+
/* Copy the IRET frame to the trampoline stack. */
667+
pushq 6*8(%rdi) /* SS */
668+
pushq 5*8(%rdi) /* RSP */
669+
pushq 4*8(%rdi) /* EFLAGS */
670+
pushq 3*8(%rdi) /* CS */
671+
pushq 2*8(%rdi) /* RIP */
672+
673+
/* Push user RDI on the trampoline stack. */
674+
pushq (%rdi)
675+
676+
/*
677+
* We are on the trampoline stack. All regs except RDI are live.
678+
* We can do future final exit work right here.
679+
*/
680+
681+
/* Restore RDI. */
682+
popq %rdi
683+
SWAPGS
637684
INTERRUPT_RETURN
638685

639686

0 commit comments

Comments
 (0)