Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

James Morse and committed by
Will Deacon
1ffe199b aa4d5d3c

+10 -2
+10 -2
arch/arm64/kernel/stacktrace.c
··· 71 71 * to task stack. 72 72 * If we reach the end of the stack - and its an interrupt stack, 73 73 * read the original task stack pointer from the dummy frame. 74 + * 75 + * Check the frame->fp we read from the bottom of the irq_stack, 76 + * and the original task stack pointer are both in current->stack. 74 77 */ 75 - if (frame->sp == irq_stack_ptr) 76 - frame->sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); 78 + if (frame->sp == irq_stack_ptr) { 79 + unsigned long orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); 80 + 81 + if(object_is_on_stack((void *)orig_sp) && 82 + object_is_on_stack((void *)frame->fp)) 83 + frame->sp = orig_sp; 84 + } 77 85 78 86 return 0; 79 87 }