[PATCH] riscv: ftrace: Fix ftrace_modify_call failure on kprobed functions
Pu Lehui <[email protected]> Sun, 2 Aug 2026 09:49:29 +0000
| Newsgroups | org.infradead.lists.linux-riscv,org.kernel.vger.bpf,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Pu Lehui <[email protected]> We are frequently hitting the following splat during the riscv bpf selftests: 00000000026dc75a: expected (7c3ff297) but got (00100073) ------------[ ftrace bug ]------------ ftrace failed to modify [<ffffffff03c44c1c>] bpf_kfunc_common_test+0x4/0x20 [bpf_testmod] actual: e7:82:c2:ce Updating ftrace call site to call a different ftrace function ftrace record flags: 80100002 (2) expected tramp: ffffffff80043904 ------------[ cut here ]------------ WARNING: kernel/trace/ftrace.c:2278 at ftrace_bug+0x46e/0x4b0, CPU#1: test_progs/98 ... [<ffffffff80008f4e>] ftrace_bug+0x46e/0x4b0 [<ffffffff803d3e86>] ftrace_replace_code+0x16e/0x170 [<ffffffff803d42b6>] ftrace_modify_all_code+0x12e/0x1b8 [<ffffffff800430f4>] arch_ftrace_update_code+0x14/0x28 [<ffffffff803e0324>] ftrace_startup+0x14c/0x2a0 [<ffffffff803e133c>] ftrace_startup_subops+0x584/0x1050 [<ffffffff804500e6>] register_ftrace_graph+0x4e6/0x1018 [<ffffffff804cf9f6>] register_fprobe_ips+0xc66/0x12f8 [<ffffffff8049abe8>] bpf_kprobe_multi_link_attach+0x5d8/0xe68 [<ffffffff8050fcaa>] __sys_bpf+0x3d5a/0x47f0 [<ffffffff805107ee>] __riscv_sys_bpf+0xae/0x168 [<ffffffff80034d78>] syscall_handler+0x60/0x100 [<ffffffff8228b4f4>] do_trap_ecall_u+0x174/0x208 [<ffffffff822b69c4>] handle_exception+0x16c/0x178 After debugging, it can be triggered by similar commands below: ``` echo do_nanosleep > set_ftrace_filter echo function > current_tracer echo 'p do_nanosleep' > kprobe_events echo 1 > events/kprobes/enable echo 'f do_nanosleep' > dynamic_events echo 1 > events/fprobes/enable ``` The reason is that attaching a kprobe to an ftrace-traced function entry replaces its initial auipc insn with ebreak. When ftrace_modify_call later runs, it expects auipc insn, so verification fails and triggers ftrace_bug. The expected auipc logic remains conceptually unchanged, and kprobe single-stepping ensures normal execution. Therefore, if the first insn is ebreak, bypassing the check to continue patching the jalr insn is safe and avoids ftrace failures. Fixes: b2137c3b6d7a ("riscv: ftrace: prepare ftrace for atomic code patching") Signed-off-by: Pu Lehui <[email protected]> --- arch/riscv/kernel/ftrace.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c index b430edfb83f4..be8b68514417 100644 --- a/arch/riscv/kernel/ftrace.c +++ b/arch/riscv/kernel/ftrace.c @@ -12,6 +12,7 @@ #include <linux/stop_machine.h> #include <asm/cacheflush.h> #include <asm/text-patching.h> +#include <asm/insn.h> #ifdef CONFIG_DYNAMIC_FTRACE void ftrace_arch_code_modify_prepare(void) @@ -63,7 +64,9 @@ static int __ftrace_modify_call(unsigned long source, unsigned long target, bool if (copy_from_kernel_nofault(replaced, (void *)source, 2 * MCOUNT_INSN_SIZE)) return -EFAULT; - if (replaced[0] != call[0]) { + /* Bypass the check if the auipc insn is a kprobe breakpoint */ + if (replaced[0] != call[0] && + !(riscv_insn_is_ebreak(replaced[0]) || riscv_insn_is_c_ebreak(replaced[0]))) { pr_err("%p: expected (%08x) but got (%08x)\n", (void *)source, call[0], replaced[0]); return -EINVAL; -- 2.34.1 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv