[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