* [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
@ 2026-01-09 9:34 Jiri Olsa
2026-01-09 9:34 ` [PATCHv2 bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper Jiri Olsa
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Jiri Olsa @ 2026-01-09 9:34 UTC (permalink / raw)
To: Masami Hiramatsu, Steven Rostedt, Will Deacon
Cc: Mahe Tardy, Peter Zijlstra, bpf, linux-trace-kernel,
linux-arm-kernel, x86, Yonghong Song, Song Liu, Andrii Nakryiko,
Mark Rutland
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>
---
v2 changes:
- moved ftrace_partial_regs_update to generic code [Will]
include/linux/ftrace_regs.h | 25 +++++++++++++++++++++++++
kernel/trace/bpf_trace.c | 1 +
2 files changed, 26 insertions(+)
diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
index 15627ceea9bc..f9a7c009cdae 100644
--- a/include/linux/ftrace_regs.h
+++ b/include/linux/ftrace_regs.h
@@ -33,6 +33,31 @@ struct ftrace_regs;
#define ftrace_regs_get_frame_pointer(fregs) \
frame_pointer(&arch_ftrace_regs(fregs)->regs)
+static __always_inline void
+ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs) { }
+
+#else
+
+/*
+ * ftrace_partial_regs_update - update the original ftrace_regs from regs
+ * @fregs: The ftrace_regs to update from @regs
+ * @regs: The partial regs from ftrace_partial_regs() that was updated
+ *
+ * Some architectures have the partial regs living in the ftrace_regs
+ * structure, whereas other architectures need to make a different copy
+ * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and
+ * if the code using @regs updates a field (like the instruction pointer or
+ * stack pointer) it may need to propagate that change to the original @fregs
+ * it retrieved the partial @regs from. Use this function to guarantee that
+ * update happens.
+ */
+static __always_inline void
+ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
+{
+ ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
+ ftrace_regs_set_return_value(fregs, regs_return_value(regs));
+}
+
#endif /* HAVE_ARCH_FTRACE_REGS */
/* This can be overridden by the architectures */
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 6e076485bf70..3a17f79b20c2 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2564,6 +2564,7 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link,
old_run_ctx = bpf_set_run_ctx(&run_ctx.session_ctx.run_ctx);
err = bpf_prog_run(link->link.prog, regs);
bpf_reset_run_ctx(old_run_ctx);
+ ftrace_partial_regs_update(fregs, bpf_kprobe_multi_pt_regs_ptr());
rcu_read_unlock();
out:
--
2.52.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCHv2 bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper
2026-01-09 9:34 [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Jiri Olsa
@ 2026-01-09 9:34 ` Jiri Olsa
2026-01-09 10:00 ` [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run bot+bpf-ci
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Jiri Olsa @ 2026-01-09 9:34 UTC (permalink / raw)
To: Masami Hiramatsu, Steven Rostedt, Will Deacon
Cc: Song Liu, Peter Zijlstra, bpf, linux-trace-kernel,
linux-arm-kernel, x86, Yonghong Song, Song Liu, Andrii Nakryiko,
Mark Rutland, Mahe Tardy
We do not actually test the bpf_override_return helper functionality
itself at the moment, only the bpf program being able to attach it.
Adding test that override prctl syscall return value on top of
kprobe and kprobe.multi.
Acked-by: Song Liu <song@kernel.org>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
.../bpf/prog_tests/kprobe_multi_test.c | 44 +++++++++++++++++++
.../bpf/progs/kprobe_multi_override.c | 15 +++++++
tools/testing/selftests/bpf/trace_helpers.h | 12 +++++
3 files changed, 71 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
index 6cfaa978bc9a..9caef222e528 100644
--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
@@ -1,4 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
+#include <errno.h>
+#include <sys/prctl.h>
#include <test_progs.h>
#include "kprobe_multi.skel.h"
#include "trace_helpers.h"
@@ -540,6 +542,46 @@ static void test_attach_override(void)
kprobe_multi_override__destroy(skel);
}
+static void test_override(void)
+{
+ struct kprobe_multi_override *skel = NULL;
+ int err;
+
+ skel = kprobe_multi_override__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load"))
+ goto cleanup;
+
+ skel->bss->pid = getpid();
+
+ /* no override */
+ err = prctl(0xffff, 0);
+ ASSERT_EQ(err, -1, "err");
+
+ /* kprobe.multi override */
+ skel->links.test_override = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override,
+ SYS_PREFIX "sys_prctl", NULL);
+ if (!ASSERT_OK_PTR(skel->links.test_override, "bpf_program__attach_kprobe_multi_opts"))
+ goto cleanup;
+
+ err = prctl(0xffff, 0);
+ ASSERT_EQ(err, 123, "err");
+
+ bpf_link__destroy(skel->links.test_override);
+ skel->links.test_override = NULL;
+
+ /* kprobe override */
+ skel->links.test_kprobe_override = bpf_program__attach_kprobe(skel->progs.test_kprobe_override,
+ false, SYS_PREFIX "sys_prctl");
+ if (!ASSERT_OK_PTR(skel->links.test_kprobe_override, "bpf_program__attach_kprobe"))
+ goto cleanup;
+
+ err = prctl(0xffff, 0);
+ ASSERT_EQ(err, 123, "err");
+
+cleanup:
+ kprobe_multi_override__destroy(skel);
+}
+
#ifdef __x86_64__
static void test_attach_write_ctx(void)
{
@@ -597,6 +639,8 @@ void test_kprobe_multi_test(void)
test_attach_api_fails();
if (test__start_subtest("attach_override"))
test_attach_override();
+ if (test__start_subtest("override"))
+ test_override();
if (test__start_subtest("session"))
test_session_skel_api();
if (test__start_subtest("session_cookie"))
diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi_override.c b/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
index 28f8487c9059..14f39fa6d515 100644
--- a/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
+++ b/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
@@ -5,9 +5,24 @@
char _license[] SEC("license") = "GPL";
+int pid = 0;
+
SEC("kprobe.multi")
int test_override(struct pt_regs *ctx)
{
+ if (bpf_get_current_pid_tgid() >> 32 != pid)
+ return 0;
+
+ bpf_override_return(ctx, 123);
+ return 0;
+}
+
+SEC("kprobe")
+int test_kprobe_override(struct pt_regs *ctx)
+{
+ if (bpf_get_current_pid_tgid() >> 32 != pid)
+ return 0;
+
bpf_override_return(ctx, 123);
return 0;
}
diff --git a/tools/testing/selftests/bpf/trace_helpers.h b/tools/testing/selftests/bpf/trace_helpers.h
index 9437bdd4afa5..a5576b2dfc26 100644
--- a/tools/testing/selftests/bpf/trace_helpers.h
+++ b/tools/testing/selftests/bpf/trace_helpers.h
@@ -4,6 +4,18 @@
#include <bpf/libbpf.h>
+#ifdef __x86_64__
+#define SYS_PREFIX "__x64_"
+#elif defined(__s390x__)
+#define SYS_PREFIX "__s390x_"
+#elif defined(__aarch64__)
+#define SYS_PREFIX "__arm64_"
+#elif defined(__riscv)
+#define SYS_PREFIX "__riscv_"
+#else
+#define SYS_PREFIX ""
+#endif
+
#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
--
2.52.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
2026-01-09 9:34 [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Jiri Olsa
2026-01-09 9:34 ` [PATCHv2 bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper Jiri Olsa
@ 2026-01-09 10:00 ` bot+bpf-ci
2026-01-09 13:47 ` Will Deacon
2026-01-09 16:18 ` Steven Rostedt
3 siblings, 0 replies; 7+ messages in thread
From: bot+bpf-ci @ 2026-01-09 10:00 UTC (permalink / raw)
To: jolsa, mhiramat, rostedt, will
Cc: mahe.tardy, peterz, bpf, linux-trace-kernel, linux-arm-kernel,
x86, yhs, songliubraving, andrii, mark.rutland, ast, andrii,
daniel, martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1539 bytes --]
> diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
> index 15627ceea9bc..f9a7c009cdae 100644
> --- a/include/linux/ftrace_regs.h
> +++ b/include/linux/ftrace_regs.h
> @@ -33,6 +33,31 @@ struct ftrace_regs;
[ ... ]
> +#else
> +
> +/*
> + * ftrace_partial_regs_update - update the original ftrace_regs from regs
> + * @fregs: The ftrace_regs to update from @regs
> + * @regs: The partial regs from ftrace_partial_regs() that was updated
[ ... ]
> + */
> +static __always_inline void
> +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> + ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
> + ftrace_regs_set_return_value(fregs, regs_return_value(regs));
^^^^^
Should the fregs parameter be non-const here? On architectures with
HAVE_ARCH_FTRACE_REGS (arm64, riscv), the setter functions expect a
non-const pointer:
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, ...)
ftrace_regs_set_return_value(struct ftrace_regs *fregs, ...)
Passing the const-qualified fregs to these functions discards the const
qualifier, which may cause compiler warnings with -Werror or undefined
behavior since the setters do modify the ftrace_regs structure.
> +}
> +
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/20847954035
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
2026-01-09 9:34 [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Jiri Olsa
2026-01-09 9:34 ` [PATCHv2 bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper Jiri Olsa
2026-01-09 10:00 ` [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run bot+bpf-ci
@ 2026-01-09 13:47 ` Will Deacon
2026-01-09 16:19 ` Steven Rostedt
2026-01-10 17:06 ` Jiri Olsa
2026-01-09 16:18 ` Steven Rostedt
3 siblings, 2 replies; 7+ messages in thread
From: Will Deacon @ 2026-01-09 13:47 UTC (permalink / raw)
To: Jiri Olsa
Cc: Masami Hiramatsu, Steven Rostedt, Mahe Tardy, Peter Zijlstra, bpf,
linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
Song Liu, Andrii Nakryiko, Mark Rutland
On Fri, Jan 09, 2026 at 10:34:53AM +0100, Jiri Olsa wrote:
> 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>
> ---
> v2 changes:
> - moved ftrace_partial_regs_update to generic code [Will]
>
> include/linux/ftrace_regs.h | 25 +++++++++++++++++++++++++
> kernel/trace/bpf_trace.c | 1 +
> 2 files changed, 26 insertions(+)
>
> diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
> index 15627ceea9bc..f9a7c009cdae 100644
> --- a/include/linux/ftrace_regs.h
> +++ b/include/linux/ftrace_regs.h
> @@ -33,6 +33,31 @@ struct ftrace_regs;
> #define ftrace_regs_get_frame_pointer(fregs) \
> frame_pointer(&arch_ftrace_regs(fregs)->regs)
>
> +static __always_inline void
> +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs) { }
> +
> +#else
> +
> +/*
> + * ftrace_partial_regs_update - update the original ftrace_regs from regs
> + * @fregs: The ftrace_regs to update from @regs
> + * @regs: The partial regs from ftrace_partial_regs() that was updated
> + *
> + * Some architectures have the partial regs living in the ftrace_regs
> + * structure, whereas other architectures need to make a different copy
> + * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and
> + * if the code using @regs updates a field (like the instruction pointer or
> + * stack pointer) it may need to propagate that change to the original @fregs
> + * it retrieved the partial @regs from. Use this function to guarantee that
> + * update happens.
> + */
> +static __always_inline void
> +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> + ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
> + ftrace_regs_set_return_value(fregs, regs_return_value(regs));
> +}
I think the AI thingy is right about dropping the const qualifier here
but overall I prefer this to the previous revisions. Thanks for sticking
with it!
Acked-by: Will Deacon <will@kernel.org>
Will
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
2026-01-09 9:34 [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Jiri Olsa
` (2 preceding siblings ...)
2026-01-09 13:47 ` Will Deacon
@ 2026-01-09 16:18 ` Steven Rostedt
3 siblings, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2026-01-09 16:18 UTC (permalink / raw)
To: Jiri Olsa
Cc: Masami Hiramatsu, Will Deacon, Mahe Tardy, Peter Zijlstra, bpf,
linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
Song Liu, Andrii Nakryiko, Mark Rutland
On Fri, 9 Jan 2026 10:34:53 +0100
Jiri Olsa <jolsa@kernel.org> wrote:
> 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>
> ---
Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-- Steve
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
2026-01-09 13:47 ` Will Deacon
@ 2026-01-09 16:19 ` Steven Rostedt
2026-01-10 17:06 ` Jiri Olsa
1 sibling, 0 replies; 7+ messages in thread
From: Steven Rostedt @ 2026-01-09 16:19 UTC (permalink / raw)
To: Will Deacon
Cc: Jiri Olsa, Masami Hiramatsu, Mahe Tardy, Peter Zijlstra, bpf,
linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
Song Liu, Andrii Nakryiko, Mark Rutland
On Fri, 9 Jan 2026 13:47:23 +0000
Will Deacon <will@kernel.org> wrote:
> I think the AI thingy is right about dropping the const qualifier here
> but overall I prefer this to the previous revisions. Thanks for sticking
> with it!
Yep, I missed that too :-p
I do think AI is better at reviewing than writing code ;-)
-- Steve
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
2026-01-09 13:47 ` Will Deacon
2026-01-09 16:19 ` Steven Rostedt
@ 2026-01-10 17:06 ` Jiri Olsa
1 sibling, 0 replies; 7+ messages in thread
From: Jiri Olsa @ 2026-01-10 17:06 UTC (permalink / raw)
To: Will Deacon
Cc: Masami Hiramatsu, Steven Rostedt, Mahe Tardy, Peter Zijlstra, bpf,
linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
Song Liu, Andrii Nakryiko, Mark Rutland
On Fri, Jan 09, 2026 at 01:47:23PM +0000, Will Deacon wrote:
> On Fri, Jan 09, 2026 at 10:34:53AM +0100, Jiri Olsa wrote:
> > 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>
> > ---
> > v2 changes:
> > - moved ftrace_partial_regs_update to generic code [Will]
> >
> > include/linux/ftrace_regs.h | 25 +++++++++++++++++++++++++
> > kernel/trace/bpf_trace.c | 1 +
> > 2 files changed, 26 insertions(+)
> >
> > diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
> > index 15627ceea9bc..f9a7c009cdae 100644
> > --- a/include/linux/ftrace_regs.h
> > +++ b/include/linux/ftrace_regs.h
> > @@ -33,6 +33,31 @@ struct ftrace_regs;
> > #define ftrace_regs_get_frame_pointer(fregs) \
> > frame_pointer(&arch_ftrace_regs(fregs)->regs)
> >
> > +static __always_inline void
> > +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs) { }
> > +
> > +#else
> > +
> > +/*
> > + * ftrace_partial_regs_update - update the original ftrace_regs from regs
> > + * @fregs: The ftrace_regs to update from @regs
> > + * @regs: The partial regs from ftrace_partial_regs() that was updated
> > + *
> > + * Some architectures have the partial regs living in the ftrace_regs
> > + * structure, whereas other architectures need to make a different copy
> > + * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and
> > + * if the code using @regs updates a field (like the instruction pointer or
> > + * stack pointer) it may need to propagate that change to the original @fregs
> > + * it retrieved the partial @regs from. Use this function to guarantee that
> > + * update happens.
> > + */
> > +static __always_inline void
> > +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> > +{
> > + ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
> > + ftrace_regs_set_return_value(fregs, regs_return_value(regs));
> > +}
>
> I think the AI thingy is right about dropping the const qualifier here
yes, will resend, thanks
jirka
> but overall I prefer this to the previous revisions. Thanks for sticking
> with it!
>
> Acked-by: Will Deacon <will@kernel.org>
>
> Will
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-01-10 17:06 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-09 9:34 [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Jiri Olsa
2026-01-09 9:34 ` [PATCHv2 bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper Jiri Olsa
2026-01-09 10:00 ` [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run bot+bpf-ci
2026-01-09 13:47 ` Will Deacon
2026-01-09 16:19 ` Steven Rostedt
2026-01-10 17:06 ` Jiri Olsa
2026-01-09 16:18 ` Steven Rostedt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox