From: "Alexei Starovoitov" <alexei.starovoitov@gmail.com>
To: "Xu Yunxiang" <xyx2021@mail.ustc.edu.cn>, <bpf@vger.kernel.org>
Cc: "Daniel Borkmann" <daniel@iogearbox.net>,
"Andrii Nakryiko" <andrii@kernel.org>,
"Eduard Zingerman" <eddyz87@gmail.com>,
"Kumar Kartikeya Dwivedi" <memxor@gmail.com>,
"Yonghong Song" <yonghong.song@linux.dev>
Subject: Re: [PATCH bpf 2/2] selftests/bpf: Exercise stack argument precision on state reuse
Date: Sun, 01 Nov 2026 01:58:46 +0000 [thread overview]
Message-ID: <DMJI3GWXQOC9.UA3K9X139AR@gmail.com> (raw)
In-Reply-To: <20261027061303.1754535-3-xyx2021@mail.ustc.edu.cn>
On Mon, Oct 26, 2026 at 11:13 PM Xu Yunxiang <xyx2021@mail.ustc.edu.cn> wrote:
> Build instructions and BTF directly so these tests run even when Clang
> does not yet support emitting stack arguments.
All other stack arg tests need a clang with __BPF_FEATURE_STACK_ARGUMENT.
This one doesn't have to be different.
No need for emit(), jump_to(), add_func() and a prog builder with five knobs.
> .../prog_tests/stack_arg_precision_reuse.c | 300 ++++++++++++++++++
> 1 file changed, 300 insertions(+)
300 lines of selftest for a 25 line fix ?
I feel our selftests are growing too fast.
Two asm progs in progs/verifier_stack_arg.c are enough. Like:
diff --git a/tools/testing/selftests/bpf/progs/verifier_stack_arg.c b/tools/testing/selftests/bpf/progs/verifier_stack_arg.c
index 15a1249..abf319c 100644
--- a/tools/testing/selftests/bpf/progs/verifier_stack_arg.c
+++ b/tools/testing/selftests/bpf/progs/verifier_stack_arg.c
@@ -552,6 +552,121 @@ __naked void stack_arg_may_goto_in_caller(void)
);
}
+/* arg6 is an offset into the value of map_hash_8b. 0-7 are in bounds. */
+__naked __noinline __used
+static long arg6_is_map_value_off(long a, long b, long c, long d, long e, long off)
+{
+ asm volatile (
+ "r6 = *(u64 *)(r11 + 8);"
+ "r1 = 0;"
+ "*(u64 *)(r10 - 8) = r1;"
+ "r2 = r10;"
+ "r2 += -8;"
+ "r1 = %[map_hash_8b] ll;"
+ "call %[bpf_map_lookup_elem];"
+ "if r0 == 0 goto l0_%=;"
+ "r0 += r6;"
+ "r0 = *(u8 *)(r0 + 0);"
+ "l0_%=:"
+ "exit;"
+ :
+ : __imm(bpf_map_lookup_elem),
+ __imm_addr(map_hash_8b)
+ : __clobber_all
+ );
+}
+
+SEC("tc")
+__description("stack_arg: a pruned state propagates precision of arg6")
+__failure __msg("invalid access to map value")
+__flag(BPF_F_TEST_STATE_FREQ)
+__naked void stack_arg_precision_pruned_state(void)
+{
+ asm volatile (
+ "call %[bpf_get_prandom_u32];"
+ "if r0 != 0 goto l0_%=;"
+ /* Path 1: arg6 = 0. It makes arg6 precise at l3. */
+ "*(u64 *)(r11 - 8) = 0;"
+ "goto l3_%=;"
+ "l0_%=:"
+ "if r0 == 1 goto l1_%=;"
+ /* Path 2: arg6 = r6 = 0. Pruned at l3. It has to make r6 precise at l2. */
+ "r6 = 0;"
+ "goto l2_%=;"
+ "l1_%=:"
+ /* Path 3: arg6 = r6 = 8. Out of bounds. */
+ "r6 = 8;"
+ "l2_%=:"
+ "*(u64 *)(r11 - 8) = r6;"
+ "l3_%=:"
+ "r1 = 0;"
+ "r2 = 0;"
+ "r3 = 0;"
+ "r4 = 0;"
+ "r5 = 0;"
+ "call arg6_is_map_value_off;"
+ "exit;"
+ :: __imm(bpf_get_prandom_u32)
+ : __clobber_all
+ );
+}
+
+/* The same, but backtracking of r1 sees a store through r1 and marks all scalars precise. */
+__naked __noinline __used
+static long arg6_is_map_value_off_fallback(long a, long b, long c, long d, long e, long off)
+{
+ asm volatile (
+ "r6 = *(u64 *)(r11 + 8);"
+ "r1 = 0;"
+ "*(u64 *)(r10 - 8) = r1;"
+ "r2 = r10;"
+ "r2 += -8;"
+ "r1 = %[map_hash_8b] ll;"
+ "call %[bpf_map_lookup_elem];"
+ "if r0 == 0 goto l0_%=;"
+ "r1 = r0;"
+ "*(u8 *)(r1 + 0) = 0;"
+ "r1 -= r0;"
+ "r1 &= 0;"
+ "r1 += r6;"
+ "r0 += r1;"
+ "r0 = *(u8 *)(r0 + 0);"
+ "l0_%=:"
+ "exit;"
+ :
+ : __imm(bpf_map_lookup_elem),
+ __imm_addr(map_hash_8b)
+ : __clobber_all
+ );
+}
+
+SEC("tc")
+__description("stack_arg: forcing all scalars precise covers arg6")
+__failure __msg("invalid access to map value")
+__flag(BPF_F_TEST_STATE_FREQ)
+__naked void stack_arg_precision_fallback(void)
+{
+ asm volatile (
+ "call %[bpf_get_prandom_u32];"
+ "if r0 != 0 goto l0_%=;"
+ "*(u64 *)(r11 - 8) = 0;"
+ "goto l1_%=;"
+ "l0_%=:"
+ /* Out of bounds. Must not be pruned at l1. */
+ "*(u64 *)(r11 - 8) = 8;"
+ "l1_%=:"
+ "r1 = 0;"
+ "r2 = 0;"
+ "r3 = 0;"
+ "r4 = 0;"
+ "r5 = 0;"
+ "call arg6_is_map_value_off_fallback;"
+ "exit;"
+ :: __imm(bpf_get_prandom_u32)
+ : __clobber_all
+ );
+}
+
#else
SEC("socket")
Patch 1 looks good.
pw-bot: cr
prev parent reply other threads:[~2026-11-01 1:58 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-27 6:13 [PATCH bpf 0/2] bpf: Fix stack argument precision propagation Xu Yunxiang
2026-10-27 6:13 ` [PATCH bpf 1/2] bpf: Propagate scalar precision through stack arguments Xu Yunxiang
2026-10-27 6:13 ` [PATCH bpf 2/2] selftests/bpf: Exercise stack argument precision on state reuse Xu Yunxiang
2026-10-27 6:27 ` sashiko-bot
2026-11-01 1:58 ` Alexei Starovoitov [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DMJI3GWXQOC9.UA3K9X139AR@gmail.com \
--to=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=memxor@gmail.com \
--cc=xyx2021@mail.ustc.edu.cn \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.