| From 89f63566d53c59803e46011854b55f74e0bef6de Mon Sep 17 00:00:00 2001 |
| From: Vasily Gorbik <gor@linux.ibm.com> |
| Date: Wed, 27 Nov 2019 18:12:04 +0100 |
| Subject: [PATCH] s390/unwind: filter out unreliable bogus %r14 |
| |
| commit bf018ee644897d7982e1b8dd8b15e97db6e1a4da upstream. |
| |
| Currently unwinder unconditionally returns %r14 from the first frame |
| pointed by %r15 from pt_regs. A task could be interrupted when a function |
| already allocated this frame (if it needs it) for its callees or to |
| store local variables. In that case this frame would contain random |
| values from stack or values stored there by a callee. As we are only |
| interested in %r14 to get potential return address, skip bogus return |
| addresses which doesn't belong to kernel text. |
| |
| This helps to avoid duplicating filtering logic in unwider users, most |
| of which use unwind_get_return_address() and would choke on bogus 0 |
| address returned by it otherwise. |
| |
| Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> |
| Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/s390/kernel/unwind_bc.c b/arch/s390/kernel/unwind_bc.c |
| index ea00f703f951..5cee3b8fe8e6 100644 |
| --- a/arch/s390/kernel/unwind_bc.c |
| +++ b/arch/s390/kernel/unwind_bc.c |
| @@ -60,6 +60,11 @@ bool unwind_next_frame(struct unwind_state *state) |
| ip = READ_ONCE_TASK_STACK(state->task, sf->gprs[8]); |
| reliable = false; |
| regs = NULL; |
| + if (!__kernel_text_address(ip)) { |
| + /* skip bogus %r14 */ |
| + state->regs = NULL; |
| + return unwind_next_frame(state); |
| + } |
| } else { |
| sf = (struct stack_frame *) state->sp; |
| sp = READ_ONCE_TASK_STACK(state->task, sf->back_chain); |
| -- |
| 2.7.4 |
| |