Skip to content

Commit 3c73b81

Browse files
amlutoKAGA-KOKO
authored andcommitted
x86/entry, selftests: Further improve user entry sanity checks
Chasing down a Xen bug caused me to realize that the new entry sanity checks are still fairly weak. Add some more checks. Signed-off-by: Andy Lutomirski <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/881de09e786ab93ce56ee4a2437ba2c308afe7a9.1593795633.git.luto@kernel.org
1 parent db5b2c5 commit 3c73b81

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

arch/x86/entry/common.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,23 @@
4949
static void check_user_regs(struct pt_regs *regs)
5050
{
5151
if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) {
52+
/*
53+
* Make sure that the entry code gave us a sensible EFLAGS
54+
* register. Native because we want to check the actual CPU
55+
* state, not the interrupt state as imagined by Xen.
56+
*/
57+
unsigned long flags = native_save_fl();
58+
WARN_ON_ONCE(flags & (X86_EFLAGS_AC | X86_EFLAGS_DF |
59+
X86_EFLAGS_NT));
60+
61+
/* We think we came from user mode. Make sure pt_regs agrees. */
62+
WARN_ON_ONCE(!user_mode(regs));
63+
64+
/*
65+
* All entries from user mode (except #DF) should be on the
66+
* normal thread stack and should have user pt_regs in the
67+
* correct location.
68+
*/
5269
WARN_ON_ONCE(!on_thread_stack());
5370
WARN_ON_ONCE(regs != task_pt_regs(current));
5471
}
@@ -577,6 +594,7 @@ SYSCALL_DEFINE0(ni_syscall)
577594
bool noinstr idtentry_enter_cond_rcu(struct pt_regs *regs)
578595
{
579596
if (user_mode(regs)) {
597+
check_user_regs(regs);
580598
enter_from_user_mode();
581599
return false;
582600
}
@@ -710,6 +728,7 @@ void noinstr idtentry_exit_cond_rcu(struct pt_regs *regs, bool rcu_exit)
710728
*/
711729
void noinstr idtentry_enter_user(struct pt_regs *regs)
712730
{
731+
check_user_regs(regs);
713732
enter_from_user_mode();
714733
}
715734

tools/testing/selftests/x86/syscall_nt.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,16 @@ int main(void)
8181
printf("[RUN]\tSet NT|AC|TF and issue a syscall\n");
8282
do_it(X86_EFLAGS_NT | X86_EFLAGS_AC | X86_EFLAGS_TF);
8383

84+
/*
85+
* Now try DF. This is evil and it's plausible that we will crash
86+
* glibc, but glibc would have to do something rather surprising
87+
* for this to happen.
88+
*/
89+
printf("[RUN]\tSet DF and issue a syscall\n");
90+
do_it(X86_EFLAGS_DF);
91+
92+
printf("[RUN]\tSet TF|DF and issue a syscall\n");
93+
do_it(X86_EFLAGS_TF | X86_EFLAGS_DF);
94+
8495
return nerrs == 0 ? 0 : 1;
8596
}

0 commit comments

Comments
 (0)