Commit 060ea84a authored by Chunyan Zhang's avatar Chunyan Zhang Committed by Paul Walmsley
Browse files

riscv: stacktrace: Disable KASAN checks for non-current tasks

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
84936118 ("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: 5d8544e2 ("RISC-V: Generic library routines and assembly")
Co-developed-by: default avatarJiakai Xu <xujiakai2025@iscas.ac.cn>
Signed-off-by: default avatarJiakai Xu <xujiakai2025@iscas.ac.cn>
Signed-off-by: default avatarChunyan 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: default avatarPaul Walmsley <pjw@kernel.org>
parent dcb6fa37
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -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) {