diff options
author | Will Deacon <will.deacon@arm.com> | 2019-04-08 12:56:34 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2019-04-08 13:05:24 -0400 |
commit | 1e6f5440a6814d28c32d347f338bfef68bc3e69d (patch) | |
tree | 4010520c549266a7637d2587f0a541355da026b2 | |
parent | 5a3ae7b314a2259b1188b22b392f5eba01e443ee (diff) |
arm64: backtrace: Don't bother trying to unwind the userspace stack
Calling dump_backtrace() with a pt_regs argument corresponding to
userspace doesn't make any sense and our unwinder will simply print
"Call trace:" before unwinding the stack looking for user frames.
Rather than go through this song and dance, just return early if we're
passed a user register state.
Cc: <stable@vger.kernel.org>
Fixes: 1149aad10b1e ("arm64: Add dump_backtrace() in show_regs")
Reported-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | arch/arm64/kernel/traps.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 8ad119c3f665..29755989f616 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c | |||
@@ -102,10 +102,16 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) | |||
102 | void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | 102 | void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) |
103 | { | 103 | { |
104 | struct stackframe frame; | 104 | struct stackframe frame; |
105 | int skip; | 105 | int skip = 0; |
106 | 106 | ||
107 | pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); | 107 | pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); |
108 | 108 | ||
109 | if (regs) { | ||
110 | if (user_mode(regs)) | ||
111 | return; | ||
112 | skip = 1; | ||
113 | } | ||
114 | |||
109 | if (!tsk) | 115 | if (!tsk) |
110 | tsk = current; | 116 | tsk = current; |
111 | 117 | ||
@@ -126,7 +132,6 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
126 | frame.graph = 0; | 132 | frame.graph = 0; |
127 | #endif | 133 | #endif |
128 | 134 | ||
129 | skip = !!regs; | ||
130 | printk("Call trace:\n"); | 135 | printk("Call trace:\n"); |
131 | do { | 136 | do { |
132 | /* skip until specified stack frame */ | 137 | /* skip until specified stack frame */ |
@@ -176,15 +181,13 @@ static int __die(const char *str, int err, struct pt_regs *regs) | |||
176 | return ret; | 181 | return ret; |
177 | 182 | ||
178 | print_modules(); | 183 | print_modules(); |
179 | __show_regs(regs); | ||
180 | pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", | 184 | pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", |
181 | TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), | 185 | TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), |
182 | end_of_stack(tsk)); | 186 | end_of_stack(tsk)); |
187 | show_regs(regs); | ||
183 | 188 | ||
184 | if (!user_mode(regs)) { | 189 | if (!user_mode(regs)) |
185 | dump_backtrace(regs, tsk); | ||
186 | dump_instr(KERN_EMERG, regs); | 190 | dump_instr(KERN_EMERG, regs); |
187 | } | ||
188 | 191 | ||
189 | return ret; | 192 | return ret; |
190 | } | 193 | } |