diff options
author | Andy Lutomirski <luto@kernel.org> | 2016-07-14 16:22:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-07-15 04:26:27 -0400 |
commit | 98f30b1207932b6553ea605c99393d8afca12324 (patch) | |
tree | 5149ed332c37aaf207a3417a9e0a49d840590c6e | |
parent | 9a2e9da3e003112399f2863b7b6b911043c01895 (diff) |
x86/dumpstack/64: Handle faults when printing the "Stack: " part of an OOPS
If we overflow the stack into a guard page, we'll recursively fault
when trying to dump the contents of the guard page. Use
probe_kernel_address() so we can recover if this happens.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/e626d47a55d7b04dcb1b4d33faa95e8505b217c8.1468527351.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/kernel/dumpstack_64.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index d558a8a49016..2552a1eadfed 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c | |||
@@ -272,6 +272,8 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | |||
272 | 272 | ||
273 | stack = sp; | 273 | stack = sp; |
274 | for (i = 0; i < kstack_depth_to_print; i++) { | 274 | for (i = 0; i < kstack_depth_to_print; i++) { |
275 | unsigned long word; | ||
276 | |||
275 | if (stack >= irq_stack && stack <= irq_stack_end) { | 277 | if (stack >= irq_stack && stack <= irq_stack_end) { |
276 | if (stack == irq_stack_end) { | 278 | if (stack == irq_stack_end) { |
277 | stack = (unsigned long *) (irq_stack_end[-1]); | 279 | stack = (unsigned long *) (irq_stack_end[-1]); |
@@ -281,12 +283,18 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | |||
281 | if (kstack_end(stack)) | 283 | if (kstack_end(stack)) |
282 | break; | 284 | break; |
283 | } | 285 | } |
286 | |||
287 | if (probe_kernel_address(stack, word)) | ||
288 | break; | ||
289 | |||
284 | if ((i % STACKSLOTS_PER_LINE) == 0) { | 290 | if ((i % STACKSLOTS_PER_LINE) == 0) { |
285 | if (i != 0) | 291 | if (i != 0) |
286 | pr_cont("\n"); | 292 | pr_cont("\n"); |
287 | printk("%s %016lx", log_lvl, *stack++); | 293 | printk("%s %016lx", log_lvl, word); |
288 | } else | 294 | } else |
289 | pr_cont(" %016lx", *stack++); | 295 | pr_cont(" %016lx", word); |
296 | |||
297 | stack++; | ||
290 | touch_nmi_watchdog(); | 298 | touch_nmi_watchdog(); |
291 | } | 299 | } |
292 | preempt_enable(); | 300 | preempt_enable(); |