Commit 97193702 authored by Joerg Roedel's avatar Joerg Roedel Committed by Thomas Gleixner

x86/entry/32: Add debug code to check entry/exit CR3

Add code to check whether the kernel is entered and left with the correct
CR3 and make it depend on CONFIG_DEBUG_ENTRY.  This is needed because there
is no NX protection of user-addresses in the kernel-CR3 on x86-32 and that
type of bug would not be detected otherwise.
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarPavel Machek <pavel@ucw.cz>
Cc: "H . Peter Anvin" <hpa@zytor.com>
Cc: linux-mm@kvack.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: David Laight <David.Laight@aculab.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Eduardo Valentin <eduval@amazon.com>
Cc: Greg KH <gregkh@linuxfoundation.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: aliguori@amazon.com
Cc: daniel.gruss@iaik.tugraz.at
Cc: hughd@google.com
Cc: keescook@google.com
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Waiman Long <llong@redhat.com>
Cc: "David H . Gutteridge" <dhgutteridge@sympatico.ca>
Cc: joro@8bytes.org
Link: https://lkml.kernel.org/r/1531906876-13451-40-git-send-email-joro@8bytes.org
parent 5e810595
...@@ -166,6 +166,24 @@ ...@@ -166,6 +166,24 @@
.Lend_\@: .Lend_\@:
.endm .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 * Switch to kernel cr3 if not already loaded and return current cr3 in
* \scratch_reg * \scratch_reg
...@@ -213,6 +231,8 @@ ...@@ -213,6 +231,8 @@
.macro SAVE_ALL_NMI cr3_reg:req .macro SAVE_ALL_NMI cr3_reg:req
SAVE_ALL SAVE_ALL
BUG_IF_WRONG_CR3
/* /*
* Now switch the CR3 when PTI is enabled. * Now switch the CR3 when PTI is enabled.
* *
...@@ -224,6 +244,7 @@ ...@@ -224,6 +244,7 @@
.Lend_\@: .Lend_\@:
.endm .endm
/* /*
* This is a sneaky trick to help the unwinder find pt_regs on the stack. The * 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 * frame pointer is replaced with an encoded pointer to pt_regs. The encoding
...@@ -287,6 +308,8 @@ ...@@ -287,6 +308,8 @@
.Lswitched_\@: .Lswitched_\@:
BUG_IF_WRONG_CR3
RESTORE_REGS pop=\pop RESTORE_REGS pop=\pop
.endm .endm
...@@ -357,6 +380,8 @@ ...@@ -357,6 +380,8 @@
ALTERNATIVE "", "jmp .Lend_\@", X86_FEATURE_XENPV ALTERNATIVE "", "jmp .Lend_\@", X86_FEATURE_XENPV
BUG_IF_WRONG_CR3
SWITCH_TO_KERNEL_CR3 scratch_reg=%eax SWITCH_TO_KERNEL_CR3 scratch_reg=%eax
/* /*
...@@ -799,6 +824,7 @@ ENTRY(entry_SYSENTER_32) ...@@ -799,6 +824,7 @@ ENTRY(entry_SYSENTER_32)
*/ */
pushfl pushfl
pushl %eax pushl %eax
BUG_IF_WRONG_CR3 no_user_check=1
SWITCH_TO_KERNEL_CR3 scratch_reg=%eax SWITCH_TO_KERNEL_CR3 scratch_reg=%eax
popl %eax popl %eax
popfl popfl
...@@ -893,6 +919,7 @@ ENTRY(entry_SYSENTER_32) ...@@ -893,6 +919,7 @@ ENTRY(entry_SYSENTER_32)
* whereas POPF does not.) * whereas POPF does not.)
*/ */
btrl $X86_EFLAGS_IF_BIT, (%esp) btrl $X86_EFLAGS_IF_BIT, (%esp)
BUG_IF_WRONG_CR3 no_user_check=1
popfl popfl
popl %eax popl %eax
...@@ -970,6 +997,8 @@ restore_all: ...@@ -970,6 +997,8 @@ restore_all:
/* Switch back to user CR3 */ /* Switch back to user CR3 */
SWITCH_TO_USER_CR3 scratch_reg=%eax SWITCH_TO_USER_CR3 scratch_reg=%eax
BUG_IF_WRONG_CR3
/* Restore user state */ /* Restore user state */
RESTORE_REGS pop=4 # skip orig_eax/error_code RESTORE_REGS pop=4 # skip orig_eax/error_code
.Lirq_return: .Lirq_return:
...@@ -983,6 +1012,7 @@ restore_all: ...@@ -983,6 +1012,7 @@ restore_all:
restore_all_kernel: restore_all_kernel:
TRACE_IRQS_IRET TRACE_IRQS_IRET
PARANOID_EXIT_TO_KERNEL_MODE PARANOID_EXIT_TO_KERNEL_MODE
BUG_IF_WRONG_CR3
RESTORE_REGS 4 RESTORE_REGS 4
jmp .Lirq_return jmp .Lirq_return
...@@ -990,6 +1020,19 @@ restore_all_kernel: ...@@ -990,6 +1020,19 @@ restore_all_kernel:
ENTRY(iret_exc ) ENTRY(iret_exc )
pushl $0 # no error code pushl $0 # no error code
pushl $do_iret_error 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 jmp common_exception
.previous .previous
_ASM_EXTABLE(.Lirq_return, iret_exc) _ASM_EXTABLE(.Lirq_return, iret_exc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment