Skip to content

Commit 6879298

Browse files
committed
x86/entry/64: Prevent clobbering of saved CR2 value
The recent fix for CR2 corruption introduced a new way to reliably corrupt the saved CR2 value. CR2 is saved early in the entry code in RDX, which is the third argument to the fault handling functions. But it missed that between saving and invoking the fault handler enter_from_user_mode() can be called. RDX is a caller saved register so the invoked function can freely clobber it with the obvious consequences. The TRACE_IRQS_OFF call is safe as it calls through the thunk which preserves RDX, but TRACE_IRQS_OFF_DEBUG is not because it also calls into C-code outside of the thunk. Store CR2 in R12 instead which is a callee saved register and move R12 to RDX just before calling the fault handler. Fixes: a0d14b8 ("x86/mm, tracing: Fix CR2 corruption") Reported-by: Sean Christopherson <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent e320ab3 commit 6879298

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

arch/x86/entry/entry_64.S

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,12 @@ apicinterrupt IRQ_WORK_VECTOR irq_work_interrupt smp_irq_work_interrupt
875875
UNWIND_HINT_REGS
876876

877877
.if \read_cr2
878-
GET_CR2_INTO(%rdx); /* can clobber %rax */
878+
/*
879+
* Store CR2 early so subsequent faults cannot clobber it. Use R12 as
880+
* intermediate storage as RDX can be clobbered in enter_from_user_mode().
881+
* GET_CR2_INTO can clobber RAX.
882+
*/
883+
GET_CR2_INTO(%r12);
879884
.endif
880885

881886
.if \shift_ist != -1
@@ -904,6 +909,10 @@ apicinterrupt IRQ_WORK_VECTOR irq_work_interrupt smp_irq_work_interrupt
904909
subq $\ist_offset, CPU_TSS_IST(\shift_ist)
905910
.endif
906911

912+
.if \read_cr2
913+
movq %r12, %rdx /* Move CR2 into 3rd argument */
914+
.endif
915+
907916
call \do_sym
908917

909918
.if \shift_ist != -1

0 commit comments

Comments
 (0)