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: Joerg Roedel <jroedel@suse.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Pavel 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
This commit is contained in:
parent
5e8105950a
commit
97193702c6
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user