[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