Skip to content

Commit 5fe599e

Browse files
jpoimboeIngo Molnar
authored andcommitted
x86/dumpstack: Add support for unwinding empty IRQ stacks
When an interrupt happens in entry code while running on a software IRQ stack, and the IRQ stack was empty, regs->sp will contain the stack end address (e.g., irq_stack_ptr). If the regs are passed to dump_trace(), get_stack_info() will report STACK_TYPE_UNKNOWN, causing dump_trace() to return prematurely without trying to go to the next stack. Update the bounds checking for software interrupt stacks so that the ending address is now considered part of the stack. This means that it's now possible for the 'walk_stack' callbacks -- print_context_stack() and print_context_stack_bp() -- to be called with an empty stack. But that's fine; they're already prepared to deal with that due to their on_stack() checks. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Byungchul Park <byungchul.park@lge.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Kees Cook <keescook@chromium.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Nilay Vaish <nilayvaish@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/5a5e5de92dcf11e8dc6b6e8e50ad7639d067830b.1473905218.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent cb76c93 commit 5fe599e

File tree

2 files changed

+15
-3
lines changed

2 files changed

+15
-3
lines changed

arch/x86/kernel/dumpstack_32.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
3535
unsigned long *begin = (unsigned long *)this_cpu_read(hardirq_stack);
3636
unsigned long *end = begin + (THREAD_SIZE / sizeof(long));
3737

38-
if (stack < begin || stack >= end)
38+
/*
39+
* This is a software stack, so 'end' can be a valid stack pointer.
40+
* It just means the stack is empty.
41+
*/
42+
if (stack < begin || stack > end)
3943
return false;
4044

4145
info->type = STACK_TYPE_IRQ;
@@ -56,7 +60,11 @@ static bool in_softirq_stack(unsigned long *stack, struct stack_info *info)
5660
unsigned long *begin = (unsigned long *)this_cpu_read(softirq_stack);
5761
unsigned long *end = begin + (THREAD_SIZE / sizeof(long));
5862

59-
if (stack < begin || stack >= end)
63+
/*
64+
* This is a software stack, so 'end' can be a valid stack pointer.
65+
* It just means the stack is empty.
66+
*/
67+
if (stack < begin || stack > end)
6068
return false;
6169

6270
info->type = STACK_TYPE_SOFTIRQ;

arch/x86/kernel/dumpstack_64.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ static bool in_irq_stack(unsigned long *stack, struct stack_info *info)
9090
unsigned long *end = (unsigned long *)this_cpu_read(irq_stack_ptr);
9191
unsigned long *begin = end - (IRQ_STACK_SIZE / sizeof(long));
9292

93-
if (stack < begin || stack >= end)
93+
/*
94+
* This is a software stack, so 'end' can be a valid stack pointer.
95+
* It just means the stack is empty.
96+
*/
97+
if (stack < begin || stack > end)
9498
return false;
9599

96100
info->type = STACK_TYPE_IRQ;

0 commit comments

Comments
 (0)