From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Yonghong Song <yonghong.song@linux.dev>,
Eduard Zingerman <eddyz87@gmail.com>,
Alexei Starovoitov <ast@kernel.org>,
Sasha Levin <sashal@kernel.org>,
nathan@kernel.org, memxor@gmail.com, andrii@kernel.org,
emil@etsalapatis.com, bpf@vger.kernel.org, llvm@lists.linux.dev
Subject: [PATCH AUTOSEL 6.17-6.12] selftests/bpf: Fix selftest verifier_arena_large failure
Date: Thu, 9 Oct 2025 11:54:50 -0400 [thread overview]
Message-ID: <20251009155752.773732-24-sashal@kernel.org> (raw)
In-Reply-To: <20251009155752.773732-1-sashal@kernel.org>
From: Yonghong Song <yonghong.song@linux.dev>
[ Upstream commit 5a427fddec5e76360725a0f03df3a2a003efbe2e ]
With latest llvm22, I got the following verification failure:
...
; int big_alloc2(void *ctx) @ verifier_arena_large.c:207
0: (b4) w6 = 1 ; R6_w=1
...
; if (err) @ verifier_arena_large.c:233
53: (56) if w6 != 0x0 goto pc+62 ; R6=0
54: (b7) r7 = -4 ; R7_w=-4
55: (18) r8 = 0x7f4000000000 ; R8_w=scalar()
57: (bf) r9 = addr_space_cast(r8, 0, 1) ; R8_w=scalar() R9_w=arena
58: (b4) w6 = 5 ; R6_w=5
; pg = page[i]; @ verifier_arena_large.c:238
59: (bf) r1 = r7 ; R1_w=-4 R7_w=-4
60: (07) r1 += 4 ; R1_w=0
61: (79) r2 = *(u64 *)(r9 +0) ; R2_w=scalar() R9_w=arena
; if (*pg != i) @ verifier_arena_large.c:239
62: (bf) r3 = addr_space_cast(r2, 0, 1) ; R2_w=scalar() R3_w=arena
63: (71) r3 = *(u8 *)(r3 +0) ; R3_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=255,var_off=(0x0; 0xff))
64: (5d) if r1 != r3 goto pc+51 ; R1_w=0 R3_w=0
; bpf_arena_free_pages(&arena, (void __arena *)pg, 2); @ verifier_arena_large.c:241
65: (18) r1 = 0xff11000114548000 ; R1_w=map_ptr(map=arena,ks=0,vs=0)
67: (b4) w3 = 2 ; R3_w=2
68: (85) call bpf_arena_free_pages#72675 ;
69: (b7) r1 = 0 ; R1_w=0
; page[i + 1] = NULL; @ verifier_arena_large.c:243
70: (7b) *(u64 *)(r8 +8) = r1
R8 invalid mem access 'scalar'
processed 61 insns (limit 1000000) max_states_per_insn 0 total_states 6 peak_states 6 mark_read 2
=============
#489/5 verifier_arena_large/big_alloc2:FAIL
The main reason is that 'r8' in insn '70' is not an arena pointer.
Further debugging at llvm side shows that llvm commit ([1]) caused
the failure. For the original code:
page[i] = NULL;
page[i + 1] = NULL;
the llvm transformed it to something like below at source level:
__builtin_memset(&page[i], 0, 16)
Such transformation prevents llvm BPFCheckAndAdjustIR pass from
generating proper addr_space_cast insns ([2]).
Adding support in llvm BPFCheckAndAdjustIR pass should work, but
not sure that such a pattern exists or not in real applications.
At the same time, simply adding a memory barrier between two 'page'
assignment can fix the issue.
[1] https://github.com/llvm/llvm-project/pull/155415
[2] https://github.com/llvm/llvm-project/pull/84410
Cc: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20250920045805.3288551-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
YES
**Why this matters**
- Fixes a real, reproducible selftest failure with LLVM 22 where two
adjacent pointer stores get optimized into a memset, breaking BPF
verifier expectations and causing “R8 invalid mem access 'scalar'”
during big_alloc2.
- Keeps BPF selftests reliable across toolchains without changing
kernel/runtime behavior.
**What changed**
- Adds a single compiler barrier between two consecutive NULL
assignments to break LLVM’s store-combining optimization:
- Before: `page[i] = NULL;` immediately followed by `page[i + 1] =
NULL;`
- After: inserts `barrier();` between them to prevent transformation
into `__builtin_memset(...)`.
- Location in tree:
`tools/testing/selftests/bpf/progs/verifier_arena_large.c`
- In the “Free pairs of pages” loop: after freeing 2 pages
(`bpf_arena_free_pages`), the code does:
- `page[i] = NULL;` at
tools/testing/selftests/bpf/progs/verifier_arena_large.c:242
- [PATCH] `barrier();` added between the two stores
- `page[i + 1] = NULL;` at
tools/testing/selftests/bpf/progs/verifier_arena_large.c:243
- The barrier macro is available via the already-included
`bpf/bpf_helpers.h` (`barrier()` is defined as an empty inline asm
memory clobber), used elsewhere in BPF selftests, and is safe for BPF.
**Root cause and effect**
- LLVM 22 transforms two adjacent stores into a 16-byte memset when it
sees:
- `page[i] = NULL;`
- `page[i + 1] = NULL;`
- This prevents LLVM’s BPFCheckAndAdjustIR pass from inserting necessary
`addr_space_cast` for arena pointers, leading to the verifier seeing a
scalar pointer (R8) on the subsequent store and rejecting the program.
- The inserted `barrier()` prevents that transformation, ensuring LLVM
keeps separate stores and the IR pass emits `addr_space_cast`, fixing
the verifier error.
**Risk and scope**
- Minimal risk:
- Single-line change in a selftest program.
- No ABI changes, no functional changes to kernel subsystems.
- Barrier only affects compiler optimization; runtime semantics remain
identical.
- Selftest-only change:
- Does not affect production kernel behavior.
- Improves test robustness across compilers.
**Stable criteria fit**
- Important bugfix: prevents a deterministic selftest failure with a
widely used toolchain (LLVM 22).
- Small and contained: one-line addition in a single selftest file.
- No architectural changes and no cross-subsystem impact.
- No side effects beyond keeping IR and verifier expectations aligned
for this test.
- Even without an explicit “Cc: stable”, selftest fixes like this are
commonly accepted to keep CI and developer workflows healthy across
toolchains.
**Dependencies and compatibility**
- The code path is guarded by `__BPF_FEATURE_ADDR_SPACE_CAST` (see block
starting at
tools/testing/selftests/bpf/progs/verifier_arena_large.c:168), so it
only builds where the feature is available, reducing risk on older
compilers.
- `barrier()` is already defined for BPF programs via `bpf_helpers.h`,
which is included at
tools/testing/selftests/bpf/progs/verifier_arena_large.c:6, ensuring
portability across supported clang versions.
Given the above, this is a low-risk, self-contained fix for a real
breakage in selftests caused by a compiler change. It should be
backported to stable trees that contain this selftest.
tools/testing/selftests/bpf/progs/verifier_arena_large.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/testing/selftests/bpf/progs/verifier_arena_large.c b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
index 9dbdf123542d3..f19e15400b3e1 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena_large.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
@@ -240,6 +240,7 @@ int big_alloc2(void *ctx)
return 5;
bpf_arena_free_pages(&arena, (void __arena *)pg, 2);
page[i] = NULL;
+ barrier();
page[i + 1] = NULL;
cond_break;
}
--
2.51.0
next prev parent reply other threads:[~2025-10-09 15:58 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20251009155752.773732-1-sashal@kernel.org>
2025-10-09 15:54 ` [PATCH AUTOSEL 6.17-5.4] bpf: Don't use %pK through printk Sasha Levin
2025-10-09 15:54 ` [PATCH AUTOSEL 6.17-6.1] bpftool: Fix -Wuninitialized-const-pointer warnings with clang >= 21 Sasha Levin
2025-10-09 15:54 ` [PATCH AUTOSEL 6.17-6.12] bpf: Use tnums for JEQ/JNE is_branch_taken logic Sasha Levin
2025-10-09 15:54 ` [PATCH AUTOSEL 6.17-6.16] selftests/bpf: Fix incorrect array size calculation Sasha Levin
2025-10-09 15:54 ` Sasha Levin [this message]
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.1] bpf: Clear pfmemalloc flag when freeing all fragments Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-5.4] selftests/bpf: Fix bpf_prog_detach2 usage in test_lirc_mode2 Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.12] selftests/bpf: Fix flaky bpf_cookie selftest Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17] selftests: drv-net: Pull data before parsing headers Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.12] libbpf: Fix USDT SIB argument handling causing unrecognized register error Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.12] bpftool: Add CET-aware symbol matching for x86_64 architectures Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.6] bpf: Do not limit bpf_cgroup_from_id to current's namespace Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.1] selftests/bpf: Upon failures, exit with code 1 in test_xsk.sh Sasha Levin
2025-10-09 15:55 ` [PATCH AUTOSEL 6.17-6.16] selftests/bpf: Fix arena_spin_lock selftest failure Sasha Levin
2025-10-09 15:56 ` [PATCH AUTOSEL 6.17-6.6] riscv: bpf: Fix uninitialized symbol 'retval_off' Sasha Levin
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=20251009155752.773732-24-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=llvm@lists.linux.dev \
--cc=memxor@gmail.com \
--cc=nathan@kernel.org \
--cc=patches@lists.linux.dev \
--cc=stable@vger.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