6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chunyan Zhang zhangchunyan@iscas.ac.cn
[ Upstream commit 060ea84a484e852b52b938f234bf9b5503a6c910 ]
Unwinding the stack of a task other than current, KASAN would report "BUG: KASAN: out-of-bounds in walk_stackframe+0x41c/0x460"
There is a same issue on x86 and has been resolved by the commit 84936118bdf3 ("x86/unwind: Disable KASAN checks for non-current tasks") The solution could be applied to RISC-V too.
This patch also can solve the issue: https://seclists.org/oss-sec/2025/q4/23
Fixes: 5d8544e2d007 ("RISC-V: Generic library routines and assembly") Co-developed-by: Jiakai Xu xujiakai2025@iscas.ac.cn Signed-off-by: Jiakai Xu xujiakai2025@iscas.ac.cn Signed-off-by: Chunyan Zhang zhangchunyan@iscas.ac.cn Link: https://lore.kernel.org/r/20251022072608.743484-1-zhangchunyan@iscas.ac.cn [pjw@kernel.org: clean up checkpatch issues] Signed-off-by: Paul Walmsley pjw@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/riscv/kernel/stacktrace.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c index 3fe9e6edef8f1..b41b6255751cb 100644 --- a/arch/riscv/kernel/stacktrace.c +++ b/arch/riscv/kernel/stacktrace.c @@ -16,6 +16,22 @@
#ifdef CONFIG_FRAME_POINTER
+/* + * This disables KASAN checking when reading a value from another task's stack, + * since the other task could be running on another CPU and could have poisoned + * the stack in the meantime. + */ +#define READ_ONCE_TASK_STACK(task, x) \ +({ \ + unsigned long val; \ + unsigned long addr = x; \ + if ((task) == current) \ + val = READ_ONCE(addr); \ + else \ + val = READ_ONCE_NOCHECK(addr); \ + val; \ +}) + extern asmlinkage void handle_exception(void); extern unsigned long ret_from_exception_end;
@@ -69,8 +85,9 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, fp = frame->ra; pc = regs->ra; } else { - fp = frame->fp; - pc = ftrace_graph_ret_addr(current, &graph_idx, frame->ra, + fp = READ_ONCE_TASK_STACK(task, frame->fp); + pc = READ_ONCE_TASK_STACK(task, frame->ra); + pc = ftrace_graph_ret_addr(current, &graph_idx, pc, &frame->ra); if (pc >= (unsigned long)handle_exception && pc < (unsigned long)&ret_from_exception_end) {