| From 57b8e277c33620e115633cdf700a260b55095460 Mon Sep 17 00:00:00 2001 |
| From: Stafford Horne <shorne@gmail.com> |
| Date: Tue, 16 Jun 2020 06:19:46 +0900 |
| Subject: [PATCH] openrisc: Fix oops caused when dumping stack |
| |
| commit 57b8e277c33620e115633cdf700a260b55095460 upstream. |
| |
| When dumping a stack with 'cat /proc/#/stack' the kernel would oops. |
| For example: |
| |
| # cat /proc/690/stack |
| Unable to handle kernel access |
| at virtual address 0x7fc60f58 |
| |
| Oops#: 0000 |
| CPU #: 0 |
| PC: c00097fc SR: 0000807f SP: d6f09b9c |
| GPR00: 00000000 GPR01: d6f09b9c GPR02: d6f09bb8 GPR03: d6f09bc4 |
| GPR04: 7fc60f5c GPR05: c00099b4 GPR06: 00000000 GPR07: d6f09ba3 |
| GPR08: ffffff00 GPR09: c0009804 GPR10: d6f08000 GPR11: 00000000 |
| GPR12: ffffe000 GPR13: dbb86000 GPR14: 00000001 GPR15: dbb86250 |
| GPR16: 7fc60f63 GPR17: 00000f5c GPR18: d6f09bc4 GPR19: 00000000 |
| GPR20: c00099b4 GPR21: ffffffc0 GPR22: 00000000 GPR23: 00000000 |
| GPR24: 00000001 GPR25: 000002c6 GPR26: d78b6850 GPR27: 00000001 |
| GPR28: 00000000 GPR29: dbb86000 GPR30: ffffffff GPR31: dbb862fc |
| RES: 00000000 oGPR11: ffffffff |
| Process cat (pid: 702, stackpage=d79d6000) |
| |
| Stack: |
| Call trace: |
| [<598977f2>] save_stack_trace_tsk+0x40/0x74 |
| [<95063f0e>] stack_trace_save_tsk+0x44/0x58 |
| [<b557bfdd>] proc_pid_stack+0xd0/0x13c |
| [<a2df8eda>] proc_single_show+0x6c/0xf0 |
| [<e5a737b7>] seq_read+0x1b4/0x688 |
| [<2d6c7480>] do_iter_read+0x208/0x248 |
| [<2182a2fb>] vfs_readv+0x64/0x90 |
| |
| This was caused by the stack trace code in save_stack_trace_tsk using |
| the wrong stack pointer. It was using the user stack pointer instead of |
| the kernel stack pointer. Fix this by using the right stack. |
| |
| Also for good measure we add try_get_task_stack/put_task_stack to ensure |
| the task is not lost while we are walking it's stack. |
| |
| Fixes: eecac38b0423a ("openrisc: support framepointers and STACKTRACE_SUPPORT") |
| Signed-off-by: Stafford Horne <shorne@gmail.com> |
| |
| diff --git a/arch/openrisc/kernel/stacktrace.c b/arch/openrisc/kernel/stacktrace.c |
| index 43f140a28bc7..54d38809e22c 100644 |
| --- a/arch/openrisc/kernel/stacktrace.c |
| +++ b/arch/openrisc/kernel/stacktrace.c |
| @@ -13,6 +13,7 @@ |
| #include <linux/export.h> |
| #include <linux/sched.h> |
| #include <linux/sched/debug.h> |
| +#include <linux/sched/task_stack.h> |
| #include <linux/stacktrace.h> |
| |
| #include <asm/processor.h> |
| @@ -68,12 +69,25 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) |
| { |
| unsigned long *sp = NULL; |
| |
| + if (!try_get_task_stack(tsk)) |
| + return; |
| + |
| if (tsk == current) |
| sp = (unsigned long *) &sp; |
| - else |
| - sp = (unsigned long *) KSTK_ESP(tsk); |
| + else { |
| + unsigned long ksp; |
| + |
| + /* Locate stack from kernel context */ |
| + ksp = task_thread_info(tsk)->ksp; |
| + ksp += STACK_FRAME_OVERHEAD; /* redzone */ |
| + ksp += sizeof(struct pt_regs); |
| + |
| + sp = (unsigned long *) ksp; |
| + } |
| |
| unwind_stack(trace, sp, save_stack_address_nosched); |
| + |
| + put_task_stack(tsk); |
| } |
| EXPORT_SYMBOL_GPL(save_stack_trace_tsk); |
| |
| -- |
| 2.27.0 |
| |