[PATCH v3 bpf-next 3/3] selftests/bpf: Test a private stack together with stack arguments
Pu Lehui
pulehui at huawei.com
Fri Nov 6 17:16:08 PST 2026
On 2026/11/7 2:15, Chen Pei wrote:
> Add two asm programs to verifier_stack_arg.c, inside the block that is
> already gated on x86, arm64 and riscv64. A raw_tp program with a 64 byte
> frame calls a ten-argument subprog with a 64 byte frame of its own, and
> BPF_PROG_TEST_RUN runs the pair without attaching it. Args 9 and 10 stay
> in the kernel frame and arg 10 points into the caller's frame, so the two
> have to agree on where the outgoing area is. The callee returns what the
> caller stored plus arg 9, so a wrong area shows up as a wrong retval
> rather than as a crash.
>
> Suggested-by: Alexei Starovoitov <alexei.starovoitov at gmail.com>
> Signed-off-by: Chen Pei <cp0613 at linux.alibaba.com>
> ---
> .../selftests/bpf/progs/verifier_stack_arg.c | 49 +++++++++++++++++++
> 1 file changed, 49 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/progs/verifier_stack_arg.c b/tools/testing/selftests/bpf/progs/verifier_stack_arg.c
> index 146cdf81bbc4..e8108e768b89 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_stack_arg.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_stack_arg.c
> @@ -975,6 +975,55 @@ __naked void stack_arg_precision_fallback(void)
> );
> }
>
> +/* Writes both ends of its frame, then reads args 9, 10 and the frame of the caller. */
> +static __naked __noinline __used
> +long priv_stack_10args(long a, long b, long c, long d, long e, long f, long g, long h,
> + long i, long *j)
> +{
> + asm volatile (
> + "r1 = 0;"
> + "*(u64 *)(r10 - 8) = r1;"
> + "*(u64 *)(r10 - 64) = r1;"
> + "r0 = *(u64 *)(r11 + 32);"
> + "r1 = *(u64 *)(r11 + 40);"
> + "r1 = *(u64 *)(r1 + 0);"
> + "r0 += r1;"
> + "exit;"
> + ::: __clobber_all
> + );
> +}
> +
> +/*
> + * A frame of 64 bytes in a raw_tp prog goes to the private stack.
> + * arm64 and riscv64 pass args 9 and 10 on the kernel stack. On x86-64
> + * both frames stay there as well.
> + */
> +SEC("raw_tp")
> +__description("stack_arg: private stack in the caller and in the callee")
> +__success __retval(890)
> +__naked void stack_arg_priv_stack(void)
> +{
> + asm volatile (
> + "r1 = 800;"
> + "*(u64 *)(r10 - 64) = r1;"
> + "r1 = r10;"
> + "r1 += -64;"
> + "*(u64 *)(r11 - 40) = r1;"
> + "*(u64 *)(r11 - 32) = 90;"
> + "*(u64 *)(r11 - 24) = 8;"
> + "*(u64 *)(r11 - 16) = 7;"
> + "*(u64 *)(r11 - 8) = 6;"
> + "r1 = 1;"
> + "r2 = 2;"
> + "r3 = 3;"
> + "r4 = 4;"
> + "r5 = 5;"
> + "call priv_stack_10args;"
> + "exit;"
> + ::: __clobber_all
> + );
> +}
> +
> #else
>
> /* No BTF tells about this store. The insn is what JIT has to deal with. */
Reviewed-by: Pu Lehui <pulehui at huawei.com>
More information about the linux-riscv
mailing list