public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
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


  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