[PATCH bpf v2 2/2] selftests/bpf: cover the exception callback using its own BPF stack
Xu Kuohai
xukuohai at huaweicloud.com
Mon Sep 7 05:33:23 PDT 2026
On 9/7/2026 1:42 PM, Donggeun Yoo wrote:
> The existing exception tests do not reach a callback that materializes
> BPF_REG_FP into a register. They either throw from the main program,
> where BPF_REG_FP already holds the value the callback needs, or use a
> callback whose only stack accesses are frame pointer relative, which the
> arm64 JIT rewrites to be stack pointer relative.
>
> Add a test that throws from a subprogram using its own BPF stack, with a
> callback that hands the address of a local variable to
> bpf_probe_read_kernel(). The helper and the callback have to name the
> same slot for the value read back to be the one the helper stored.
>
> Signed-off-by: Donggeun Yoo <donggeunyoo.kernel at gmail.com>
> ---
> .../selftests/bpf/prog_tests/exceptions.c | 1 +
> .../testing/selftests/bpf/progs/exceptions.c | 29 +++++++++++++++++++
> 2 files changed, 30 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/exceptions.c b/tools/testing/selftests/bpf/prog_tests/exceptions.c
> index 3588d6f97fd4..639866ce09a9 100644
> --- a/tools/testing/selftests/bpf/prog_tests/exceptions.c
> +++ b/tools/testing/selftests/bpf/prog_tests/exceptions.c
> @@ -55,6 +55,7 @@ static void test_exceptions_success(void)
> RUN_SUCCESS(exception_ext, 0);
> RUN_SUCCESS(exception_ext_mod_cb_runtime, 35);
> RUN_SUCCESS(exception_throw_subprog, 1);
> + RUN_SUCCESS(exception_throw_subprog_stack_cb, 0x1234);
> RUN_SUCCESS(exception_assert_nz_gfunc, 1);
> RUN_SUCCESS(exception_assert_zero_gfunc, 1);
> RUN_SUCCESS(exception_assert_neg_gfunc, 1);
> diff --git a/tools/testing/selftests/bpf/progs/exceptions.c b/tools/testing/selftests/bpf/progs/exceptions.c
> index c8d716fbd419..2b01b45cef06 100644
> --- a/tools/testing/selftests/bpf/progs/exceptions.c
> +++ b/tools/testing/selftests/bpf/progs/exceptions.c
> @@ -212,6 +212,35 @@ int exception_throw_subprog(struct __sk_buff *ctx)
> return 0;
> }
>
> +u64 exception_cb_stack_src = 0x1234;
> +
> +/* The address handed to the helper has to be this callback's own stack
> + * slot, not one from a frame that is already gone.
> + */
> +__noinline int exception_cb_stack(u64 cookie)
> +{
> + volatile u64 val = 0xdead;
> +
> + bpf_probe_read_kernel((void *)&val, sizeof(val), &exception_cb_stack_src);
> + return val;
> +}
> +
> +/* Throws from a subprogram that has a stack of its own. */
> +__noinline static int throwing_subprog_stack(struct __sk_buff *ctx)
> +{
> + volatile u64 pad[4] = {};
> +
> + bpf_throw(pad[0]);
> + return 0;
> +}
> +
> +SEC("tc")
> +__exception_cb(exception_cb_stack)
> +int exception_throw_subprog_stack_cb(struct __sk_buff *ctx)
> +{
> + return throwing_subprog_stack(ctx);
> +}
> +
> __noinline int assert_nz_gfunc(u64 c)
> {
> volatile u64 cookie = c;
Acked-by: Xu Kuohai <xukuohai at huawei.com>
More information about the linux-arm-kernel
mailing list