Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

arm64/ftrace,bpf: Fix partial regs after bpf_prog_run

Mahe reported issue with bpf_override_return helper not working when
executed from kprobe.multi bpf program on arm.

The problem is that on arm we use alternate storage for pt_regs object
that is passed to bpf_prog_run and if any register is changed (which
is the case of bpf_override_return) it's not propagated back to actual
pt_regs object.

Fixing this by introducing and calling ftrace_partial_regs_update function
to propagate the values of changed registers (ip and stack).

Reported-by: Mahe Tardy <mahe.tardy@gmail.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Acked-by: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/bpf/20260112121157.854473-1-jolsa@kernel.org

authored by

Jiri Olsa and committed by
Andrii Nakryiko
276f3b6d 9a403a4a

+26
+25
include/linux/ftrace_regs.h
··· 33 33 #define ftrace_regs_get_frame_pointer(fregs) \ 34 34 frame_pointer(&arch_ftrace_regs(fregs)->regs) 35 35 36 + static __always_inline void 37 + ftrace_partial_regs_update(struct ftrace_regs *fregs, struct pt_regs *regs) { } 38 + 39 + #else 40 + 41 + /* 42 + * ftrace_partial_regs_update - update the original ftrace_regs from regs 43 + * @fregs: The ftrace_regs to update from @regs 44 + * @regs: The partial regs from ftrace_partial_regs() that was updated 45 + * 46 + * Some architectures have the partial regs living in the ftrace_regs 47 + * structure, whereas other architectures need to make a different copy 48 + * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and 49 + * if the code using @regs updates a field (like the instruction pointer or 50 + * stack pointer) it may need to propagate that change to the original @fregs 51 + * it retrieved the partial @regs from. Use this function to guarantee that 52 + * update happens. 53 + */ 54 + static __always_inline void 55 + ftrace_partial_regs_update(struct ftrace_regs *fregs, struct pt_regs *regs) 56 + { 57 + ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs)); 58 + ftrace_regs_set_return_value(fregs, regs_return_value(regs)); 59 + } 60 + 36 61 #endif /* HAVE_ARCH_FTRACE_REGS */ 37 62 38 63 /* This can be overridden by the architectures */
+1
kernel/trace/bpf_trace.c
··· 2564 2564 old_run_ctx = bpf_set_run_ctx(&run_ctx.session_ctx.run_ctx); 2565 2565 err = bpf_prog_run(link->link.prog, regs); 2566 2566 bpf_reset_run_ctx(old_run_ctx); 2567 + ftrace_partial_regs_update(fregs, bpf_kprobe_multi_pt_regs_ptr()); 2567 2568 rcu_read_unlock(); 2568 2569 2569 2570 out: