Re: [PATCH] riscv: ftrace: Fix ftrace_modify_call failure on kprobed functions

Pu Lehui <[email protected]>
Newsgroups org.infradead.lists.linux-riscv,org.kernel.vger.bpf,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Gentle ping~

Hi all, Is this commit looks proper?

On 2026/8/2 17:49, Pu Lehui wrote:
> 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;

_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.