diff options
author | James Morse <james.morse@arm.com> | 2015-12-10 11:22:40 +0100 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2015-12-10 13:08:09 +0100 |
commit | 1ffe199b1c9b72a8e752a9ae2a7af10128ab2ca1 (patch) | |
tree | d8b18acfe73ce9bfaaae71927c41c4b44b088388 /arch/arm64/kernel/stacktrace.c | |
parent | arm64: Add this_cpu_ptr() assembler macro for use in entry.S (diff) | |
download | linux-1ffe199b1c9b72a8e752a9ae2a7af10128ab2ca1.tar.xz linux-1ffe199b1c9b72a8e752a9ae2a7af10128ab2ca1.zip |
arm64: when walking onto the task stack, check sp & fp are in current->stack
When unwind_frame() reaches the bottom of the irq_stack, the last fp
points to the original task stack. unwind_frame() uses
IRQ_STACK_TO_TASK_STACK() to find the sp value. If either values is
wrong, we may end up walking a corrupt stack.
Check these values are sane by testing if they are both on the stack
pointed to by current->stack.
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64/kernel/stacktrace.c')
-rw-r--r-- | arch/arm64/kernel/stacktrace.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index b947eeffa5b2..d916d5b6aef6 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -71,9 +71,17 @@ int notrace unwind_frame(struct stackframe *frame) * to task stack. * If we reach the end of the stack - and its an interrupt stack, * read the original task stack pointer from the dummy frame. + * + * Check the frame->fp we read from the bottom of the irq_stack, + * and the original task stack pointer are both in current->stack. */ - if (frame->sp == irq_stack_ptr) - frame->sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); + if (frame->sp == irq_stack_ptr) { + unsigned long orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); + + if(object_is_on_stack((void *)orig_sp) && + object_is_on_stack((void *)frame->fp)) + frame->sp = orig_sp; + } return 0; } |