From: Vineet Gupta <vineet.gupta@linux.dev>
To: bpf@vger.kernel.org
Cc: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
eddyz87@gmail.com, memxor@gmail.com, martin.lau@linux.dev,
song@kernel.org, yonghong.song@linux.dev, jolsa@kernel.org,
emil@etsalapatis.com, ihor.solodrai@linux.dev,
john.fastabend@gmail.com, shuah@kernel.org,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
jose.marchesi@oracle.com, david.faust@oss.qualcomm.com,
Vineet Gupta <vineet.gupta@linux.dev>
Subject: [PATCH bpf-next v4 5/8] selftests/bpf: write the mixed arena/scalar ALU tests in asm
Date: Tue, 3 Nov 2026 10:18:13 -0800 [thread overview]
Message-ID: <20261103181816.254686-6-vineet.gupta@linux.dev> (raw)
In-Reply-To: <20261103181816.254686-1-vineet.gupta@linux.dev>
They fail to build with BPF_GCC:
progs/verifier_arena.c:566:5: error: optimization may eliminate reads and/or writes to register variables [-Werror=volatile-register-var]
for
volatile register __u64 reg asm("r3");
and GCC means it. With the warning silenced it drops both scalar
accesses, leaving nothing that uses r3 as a scalar:
call 7
if w0 == 0 goto .L136
r9 = arena ll;r3 = 0;r3 = addr_space_cast(r3, 0, 1);
.L136:
r0 = 0
exit
`reg = 1ULL << 32' and `reg += 1' are both gone. The tests need one
instruction reached with r3 live as a scalar on one path and as an
arena pointer on the other; what is left gives the verifier no reason
to reject anything, so the __failure expectation would not hold. A
local register variable is not guaranteed to survive a helper call
either, which GCC is also entitled to act on.
Nothing here needs a compiler to allocate registers, so write the
whole body in asm like mixed_arena_stack_atomic below, which tests the
same shape. Both compilers then emit the same sequence, with the
branch landing on the shared ALU op:
call 7
r6=r0
r3=1
r3<<=32
if w6==0 goto 4 <- lands on r3+=1
r9=0 ll
r3=0
r3 = addr_space_cast(r3, 0, 1)
r3+=1 <- scalar on one path, arena pointer on the other
r0=0
exit
And while here also bring in __load_if_JITed(). A program binding an
arena map is rejected in check_map_prog_compatibility() with "JIT is
required to use arena" during map resolution, before do_check() can
reach the shared instruction, so without a JIT these would fail on the
wrong message rather than skip.
Both tests become visible once 6/8 stops hiding them, and pass:
verifier_arena/mixed_arena_scalar_alu64_scalar_first -> OK
verifier_arena/mixed_arena_scalar_alu64_arena_first -> OK
Notes:
- This does need an __arena capable BPF_GCC.
- Under clang the rewrite is not a no-op: the existing version spilled r3
to the stack and did the shared ALU op on r1 reloaded from it, so the
test was not exercising one register live as both a scalar and an arena
pointer.
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
v3 -> v4: was 7/8, now ahead of the guard removal that stops hiding
these tests. Otherwise unchanged.
.../selftests/bpf/progs/verifier_arena.c | 91 +++++++++++--------
1 file changed, 51 insertions(+), 40 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/verifier_arena.c b/tools/testing/selftests/bpf/progs/verifier_arena.c
index 9b149c724160..146febd99523 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena.c
@@ -561,53 +561,64 @@ int arena_ptr_add_arena_ptr(void *ctx)
return 0;
}
+/*
+ * Tests that one insn cannot be reached with a register holding a scalar
+ * on one path and an arena pointer on the other.
+ */
SEC("syscall")
__failure __msg("same insn cannot be used with and without arena pointer")
-int mixed_arena_scalar_alu64_scalar_first(void *ctx)
-{
- volatile register __u64 reg asm("r3");
- __u32 pick_arena = bpf_get_prandom_u32();
-
- reg = 1ULL << 32;
-
- if (pick_arena) {
- asm volatile (
- "r9 = %[arena] ll;"
- "%[reg] = 0;"
- "%[reg] = addr_space_cast(%[reg], 0, 1);"
- : [reg] "=r"(reg)
- : __imm_addr(arena)
- : "r9"
- );
- }
-
- reg += 1;
-
- return 0;
+__load_if_JITed()
+__naked void mixed_arena_scalar_alu64_scalar_first(void)
+{
+ /*
+ * The r9 load is never read. libbpf binds the object's arena to
+ * every program through fd_array, so the verifier knows about it
+ * without this; the load is the fallback for a kernel without
+ * fd_array_cnt and for the light skeleton loader.
+ */
+ asm volatile (" \
+ call %[bpf_get_prandom_u32]; \
+ r6 = r0; \
+ r3 = 1; \
+ r3 <<= 32; \
+ if w6 == 0 goto 1f; \
+ r9 = %[arena] ll; \
+ r3 = 0; \
+ r3 = addr_space_cast(r3, 0, 1); \
+1: r3 += 1; \
+ r0 = 0; \
+ exit; \
+" :
+ : __imm_addr(arena),
+ __imm(bpf_get_prandom_u32)
+ : __clobber_all);
}
+/*
+ * As mixed_arena_scalar_alu64_scalar_first(), including the r9 load, with
+ * the arena pointer established first.
+ */
SEC("syscall")
__failure __msg("same insn cannot be used with and without arena pointer")
-int mixed_arena_scalar_alu64_arena_first(void *ctx)
+__load_if_JITed()
+__naked void mixed_arena_scalar_alu64_arena_first(void)
{
- volatile register __u64 reg asm("r3");
- __u32 pick_scalar = bpf_get_prandom_u32();
-
- asm volatile (
- "r9 = %[arena] ll;"
- "%[reg] = 0;"
- "%[reg] = addr_space_cast(%[reg], 0, 1);"
- : [reg] "=r"(reg)
- : __imm_addr(arena)
- : "r9"
- );
-
- if (pick_scalar)
- reg = 1ULL << 32;
-
- reg += 1;
-
- return 0;
+ asm volatile (" \
+ call %[bpf_get_prandom_u32]; \
+ r6 = r0; \
+ r9 = %[arena] ll; \
+ r3 = 0; \
+ r3 = addr_space_cast(r3, 0, 1); \
+ if w6 == 0 goto 1f; \
+ r3 = 1; \
+ r3 <<= 32; \
+1: r3 += 1; \
+ r0 = 0; \
+ exit; \
+" :
+ : __imm_addr(arena),
+ __imm(bpf_get_prandom_u32)
+ : __clobber_all);
}
SEC("syscall")
--
2.53.0-Meta
next prev parent reply other threads:[~2026-11-03 18:19 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 18:18 [PATCH bpf-next v4 0/8] selftests/bpf: let the arena tests build with GCC Vineet Gupta
2026-11-03 18:18 ` [PATCH bpf-next v4 1/8] selftests/bpf: Build callx tests with GCC that defines __BPF_FEATURE_CALLX Vineet Gupta
2026-11-03 18:18 ` [PATCH bpf-next v4 2/8] selftests/bpf: don't pass clang-only warning flags to GCC Vineet Gupta
2026-11-03 18:18 ` [PATCH bpf-next v4 3/8] selftests/bpf: make arena_base() opaque to GCC's -Warray-bounds Vineet Gupta
2026-11-03 18:18 ` [PATCH bpf-next v4 4/8] selftests/bpf: spell the addr_space_cast address spaces in decimal Vineet Gupta
2026-11-03 18:57 ` bot+bpf-ci
2026-11-03 18:18 ` Vineet Gupta [this message]
2026-11-03 18:57 ` [PATCH bpf-next v4 5/8] selftests/bpf: write the mixed arena/scalar ALU tests in asm bot+bpf-ci
2026-11-03 18:18 ` [PATCH bpf-next v4 6/8] selftests/bpf: drop the arena guards and tag the tests that need arena Vineet Gupta
2026-11-03 18:57 ` bot+bpf-ci
2026-11-03 18:18 ` [PATCH bpf-next v4 7/8] selftests/bpf: cast explicitly in the struct_ops arena triggers Vineet Gupta
2026-11-03 18:18 ` [PATCH bpf-next v4 8/8] selftests/bpf: cast explicitly in the arena subprog and callback faults Vineet Gupta
2026-11-03 21:20 ` [PATCH bpf-next v4 0/8] selftests/bpf: let the arena tests build with GCC patchwork-bot+netdevbpf
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=20261103181816.254686-6-vineet.gupta@linux.dev \
--to=vineet.gupta@linux.dev \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=david.faust@oss.qualcomm.com \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=ihor.solodrai@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=jose.marchesi@oracle.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®