Skip to content

Commit c9c2615

Browse files
amlutoKAGA-KOKO
authored andcommitted
x86/entry: Assert that syscalls are on the right stack
Now that the entry stack is a full page, it's too easy to regress the system call entry code and end up on the wrong stack without noticing. Assert that all system calls (SYSCALL64, SYSCALL32, SYSENTER, and INT80) are on the right stack and have pt_regs in the right place. Signed-off-by: Andy Lutomirski <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lkml.kernel.org/r/52059e42bb0ab8551153d012d68f7be18d72ff8e.1593191971.git.luto@kernel.org
1 parent 009bce1 commit c9c2615

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

arch/x86/entry/common.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@
4545
#define CREATE_TRACE_POINTS
4646
#include <trace/events/syscalls.h>
4747

48+
/* Check that the stack and regs on entry from user mode are sane. */
49+
static void check_user_regs(struct pt_regs *regs)
50+
{
51+
if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) {
52+
WARN_ON_ONCE(!on_thread_stack());
53+
WARN_ON_ONCE(regs != task_pt_regs(current));
54+
}
55+
}
56+
4857
#ifdef CONFIG_CONTEXT_TRACKING
4958
/**
5059
* enter_from_user_mode - Establish state when coming from user mode
@@ -127,9 +136,6 @@ static long syscall_trace_enter(struct pt_regs *regs)
127136
unsigned long ret = 0;
128137
u32 work;
129138

130-
if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
131-
BUG_ON(regs != task_pt_regs(current));
132-
133139
work = READ_ONCE(ti->flags);
134140

135141
if (work & (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU)) {
@@ -346,6 +352,8 @@ __visible noinstr void do_syscall_64(unsigned long nr, struct pt_regs *regs)
346352
{
347353
struct thread_info *ti;
348354

355+
check_user_regs(regs);
356+
349357
enter_from_user_mode();
350358
instrumentation_begin();
351359

@@ -409,6 +417,8 @@ static void do_syscall_32_irqs_on(struct pt_regs *regs)
409417
/* Handles int $0x80 */
410418
__visible noinstr void do_int80_syscall_32(struct pt_regs *regs)
411419
{
420+
check_user_regs(regs);
421+
412422
enter_from_user_mode();
413423
instrumentation_begin();
414424

@@ -460,6 +470,8 @@ __visible noinstr long do_fast_syscall_32(struct pt_regs *regs)
460470
vdso_image_32.sym_int80_landing_pad;
461471
bool success;
462472

473+
check_user_regs(regs);
474+
463475
/*
464476
* SYSENTER loses EIP, and even SYSCALL32 needs us to skip forward
465477
* so that 'regs->ip -= 2' lands back on an int $0x80 instruction.

0 commit comments

Comments
 (0)