Commit 12964443 authored by Mark Rutland's avatar Mark Rutland

arm64: add on_accessible_stack()

Both unwind_frame() and dump_backtrace() try to check whether a stack
address is sane to access, with very similar logic. Both will need
updating in order to handle overflow stacks.

Factor out this logic into a helper, so that we can avoid further
duplication when we add overflow stacks.
Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Reviewed-by: default avatarWill Deacon <will.deacon@arm.com>
Tested-by: default avatarLaura Abbott <labbott@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
parent e3067861
...@@ -57,4 +57,20 @@ static inline bool on_task_stack(struct task_struct *tsk, unsigned long sp) ...@@ -57,4 +57,20 @@ static inline bool on_task_stack(struct task_struct *tsk, unsigned long sp)
return (low <= sp && sp < high); return (low <= sp && sp < high);
} }
/*
* We can only safely access per-cpu stacks from current in a non-preemptible
* context.
*/
static inline bool on_accessible_stack(struct task_struct *tsk, unsigned long sp)
{
if (on_task_stack(tsk, sp))
return true;
if (tsk != current || preemptible())
return false;
if (on_irq_stack(sp))
return true;
return false;
}
#endif /* __ASM_STACKTRACE_H */ #endif /* __ASM_STACKTRACE_H */
...@@ -50,12 +50,7 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) ...@@ -50,12 +50,7 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
if (!tsk) if (!tsk)
tsk = current; tsk = current;
/* if (!on_accessible_stack(tsk, fp))
* Switching between stacks is valid when tracing current and in
* non-preemptible context.
*/
if (!(tsk == current && !preemptible() && on_irq_stack(fp)) &&
!on_task_stack(tsk, fp))
return -EINVAL; return -EINVAL;
frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
......
...@@ -193,8 +193,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) ...@@ -193,8 +193,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
if (in_entry_text(frame.pc)) { if (in_entry_text(frame.pc)) {
stack = frame.fp - offsetof(struct pt_regs, stackframe); stack = frame.fp - offsetof(struct pt_regs, stackframe);
if (on_task_stack(tsk, stack) || if (on_accessible_stack(tsk, stack))
(tsk == current && !preemptible() && on_irq_stack(stack)))
dump_mem("", "Exception stack", stack, dump_mem("", "Exception stack", stack,
stack + sizeof(struct pt_regs)); stack + sizeof(struct pt_regs));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment