|
@@ -166,6 +166,24 @@
|
|
|
.Lend_\@:
|
|
|
.endm
|
|
|
|
|
|
+.macro BUG_IF_WRONG_CR3 no_user_check=0
|
|
|
+#ifdef CONFIG_DEBUG_ENTRY
|
|
|
+ ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI
|
|
|
+ .if \no_user_check == 0
|
|
|
+ /* coming from usermode? */
|
|
|
+ testl $SEGMENT_RPL_MASK, PT_CS(%esp)
|
|
|
+ jz .Lend_\@
|
|
|
+ .endif
|
|
|
+ /* On user-cr3? */
|
|
|
+ movl %cr3, %eax
|
|
|
+ testl $PTI_SWITCH_MASK, %eax
|
|
|
+ jnz .Lend_\@
|
|
|
+ /* From userspace with kernel cr3 - BUG */
|
|
|
+ ud2
|
|
|
+.Lend_\@:
|
|
|
+#endif
|
|
|
+.endm
|
|
|
+
|
|
|
/*
|
|
|
* Switch to kernel cr3 if not already loaded and return current cr3 in
|
|
|
* \scratch_reg
|
|
@@ -213,6 +231,8 @@
|
|
|
.macro SAVE_ALL_NMI cr3_reg:req
|
|
|
SAVE_ALL
|
|
|
|
|
|
+ BUG_IF_WRONG_CR3
|
|
|
+
|
|
|
/*
|
|
|
* Now switch the CR3 when PTI is enabled.
|
|
|
*
|
|
@@ -224,6 +244,7 @@
|
|
|
|
|
|
.Lend_\@:
|
|
|
.endm
|
|
|
+
|
|
|
/*
|
|
|
* This is a sneaky trick to help the unwinder find pt_regs on the stack. The
|
|
|
* frame pointer is replaced with an encoded pointer to pt_regs. The encoding
|
|
@@ -287,6 +308,8 @@
|
|
|
|
|
|
.Lswitched_\@:
|
|
|
|
|
|
+ BUG_IF_WRONG_CR3
|
|
|
+
|
|
|
RESTORE_REGS pop=\pop
|
|
|
.endm
|
|
|
|
|
@@ -357,6 +380,8 @@
|
|
|
|
|
|
ALTERNATIVE "", "jmp .Lend_\@", X86_FEATURE_XENPV
|
|
|
|
|
|
+ BUG_IF_WRONG_CR3
|
|
|
+
|
|
|
SWITCH_TO_KERNEL_CR3 scratch_reg=%eax
|
|
|
|
|
|
/*
|
|
@@ -799,6 +824,7 @@ ENTRY(entry_SYSENTER_32)
|
|
|
*/
|
|
|
pushfl
|
|
|
pushl %eax
|
|
|
+ BUG_IF_WRONG_CR3 no_user_check=1
|
|
|
SWITCH_TO_KERNEL_CR3 scratch_reg=%eax
|
|
|
popl %eax
|
|
|
popfl
|
|
@@ -893,6 +919,7 @@ ENTRY(entry_SYSENTER_32)
|
|
|
* whereas POPF does not.)
|
|
|
*/
|
|
|
btrl $X86_EFLAGS_IF_BIT, (%esp)
|
|
|
+ BUG_IF_WRONG_CR3 no_user_check=1
|
|
|
popfl
|
|
|
popl %eax
|
|
|
|
|
@@ -970,6 +997,8 @@ restore_all:
|
|
|
/* Switch back to user CR3 */
|
|
|
SWITCH_TO_USER_CR3 scratch_reg=%eax
|
|
|
|
|
|
+ BUG_IF_WRONG_CR3
|
|
|
+
|
|
|
/* Restore user state */
|
|
|
RESTORE_REGS pop=4 # skip orig_eax/error_code
|
|
|
.Lirq_return:
|
|
@@ -983,6 +1012,7 @@ restore_all:
|
|
|
restore_all_kernel:
|
|
|
TRACE_IRQS_IRET
|
|
|
PARANOID_EXIT_TO_KERNEL_MODE
|
|
|
+ BUG_IF_WRONG_CR3
|
|
|
RESTORE_REGS 4
|
|
|
jmp .Lirq_return
|
|
|
|
|
@@ -990,6 +1020,19 @@ restore_all_kernel:
|
|
|
ENTRY(iret_exc )
|
|
|
pushl $0 # no error code
|
|
|
pushl $do_iret_error
|
|
|
+
|
|
|
+#ifdef CONFIG_DEBUG_ENTRY
|
|
|
+ /*
|
|
|
+ * The stack-frame here is the one that iret faulted on, so its a
|
|
|
+ * return-to-user frame. We are on kernel-cr3 because we come here from
|
|
|
+ * the fixup code. This confuses the CR3 checker, so switch to user-cr3
|
|
|
+ * as the checker expects it.
|
|
|
+ */
|
|
|
+ pushl %eax
|
|
|
+ SWITCH_TO_USER_CR3 scratch_reg=%eax
|
|
|
+ popl %eax
|
|
|
+#endif
|
|
|
+
|
|
|
jmp common_exception
|
|
|
.previous
|
|
|
_ASM_EXTABLE(.Lirq_return, iret_exc)
|