* [PATCH bpf-next 0/2] bpf: Reject mixed arena and ordinary atomic paths
@ 2026-08-13 12:01 Yiyang Chen
2026-08-13 12:01 ` [PATCH bpf-next 1/2] bpf: Check pointer type for all atomic RMW paths Yiyang Chen
2026-08-13 12:01 ` [PATCH bpf-next 2/2] selftests/bpf: Cover mixed arena and map-value atomics Yiyang Chen
0 siblings, 2 replies; 6+ messages in thread
From: Yiyang Chen @ 2026-08-13 12:01 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Yiyang Chen
Atomic RMW instructions use a single aux pointer type to select their final
instruction encoding. The verifier currently records that type only for
PTR_TO_ARENA, allowing a second path with an ordinary pointer to reach the
same instruction before fixups rewrite it to BPF_PROBE_ATOMIC.
Patch 1 records the destination type for every atomic RMW path so the existing
pointer mismatch check rejects incompatible uses of one instruction.
Patch 2 adds a verifier regression test with PTR_TO_ARENA and
PTR_TO_MAP_VALUE paths converging on one atomic add.
Yiyang Chen (2):
bpf: Check pointer type for all atomic RMW paths
selftests/bpf: Cover mixed arena and map-value atomics
Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
---
Yiyang Chen (2):
bpf: Check pointer type for all atomic RMW paths
selftests/bpf: Cover mixed arena and map-value atomics
kernel/bpf/verifier.c | 8 ++--
tools/testing/selftests/bpf/progs/verifier_arena.c | 44 ++++++++++++++++++++++
2 files changed, 47 insertions(+), 5 deletions(-)
---
base-commit: 6f033615ef8fb2374daa7e50a8ff68616bc850d2
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH bpf-next 1/2] bpf: Check pointer type for all atomic RMW paths 2026-08-13 12:01 [PATCH bpf-next 0/2] bpf: Reject mixed arena and ordinary atomic paths Yiyang Chen @ 2026-08-13 12:01 ` Yiyang Chen 2026-08-13 22:12 ` Eduard Zingerman 2026-08-13 12:01 ` [PATCH bpf-next 2/2] selftests/bpf: Cover mixed arena and map-value atomics Yiyang Chen 1 sibling, 1 reply; 6+ messages in thread From: Yiyang Chen @ 2026-08-13 12:01 UTC (permalink / raw) To: Alexei Starovoitov, Daniel Borkmann, John Fastabend, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai, Shuah Khan Cc: bpf, linux-kernel, linux-kselftest, Yiyang Chen Atomic RMW verification records an instruction pointer type only when the current destination is PTR_TO_ARENA. A second path can therefore reach the same instruction with an ordinary pointer without comparing it against the saved arena type. The post-verification fixup uses the saved type to rewrite the instruction to BPF_PROBE_ATOMIC for every path. Record the actual destination type for all atomic RMW paths so the existing mismatch check rejects incompatible uses of one instruction. Fixes: d503a04f8bc0 ("bpf: Add support for certain atomics in bpf_arena to x86 JIT") Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn> --- kernel/bpf/verifier.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 164d16c243ca6..3d672f6665bec 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6509,11 +6509,9 @@ static int check_atomic_rmw(struct bpf_verifier_env *env, if (err) return err; - if (is_arena_reg(env, insn->dst_reg)) { - err = save_aux_ptr_type(env, PTR_TO_ARENA, false); - if (err) - return err; - } + err = save_aux_ptr_type(env, dst_reg->type, false); + if (err) + return err; /* Check whether we can write into the same memory. */ err = check_mem_access(env, env->insn_idx, dst_reg, argno_from_reg(insn->dst_reg), insn->off, BPF_SIZE(insn->code), BPF_WRITE, -1, true, false); -- 2.43.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: Check pointer type for all atomic RMW paths 2026-08-13 12:01 ` [PATCH bpf-next 1/2] bpf: Check pointer type for all atomic RMW paths Yiyang Chen @ 2026-08-13 22:12 ` Eduard Zingerman 0 siblings, 0 replies; 6+ messages in thread From: Eduard Zingerman @ 2026-08-13 22:12 UTC (permalink / raw) To: Yiyang Chen, Alexei Starovoitov, Daniel Borkmann, John Fastabend, Andrii Nakryiko, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai, Shuah Khan Cc: bpf, linux-kernel, linux-kselftest On Thu, 2026-08-13 at 12:01 +0000, Yiyang Chen wrote: > Atomic RMW verification records an instruction pointer type only when the > current destination is PTR_TO_ARENA. A second path can therefore reach the > same instruction with an ordinary pointer without comparing it against the > saved arena type. > > The post-verification fixup uses the saved type to rewrite the instruction > to BPF_PROBE_ATOMIC for every path. Record the actual destination type for > all atomic RMW paths so the existing mismatch check rejects incompatible > uses of one instruction. > > Fixes: d503a04f8bc0 ("bpf: Add support for certain atomics in bpf_arena to x86 JIT") > Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn> > --- Acked-by: Eduard Zingerman <eddyz87@gmail.com> Looks like this was the only missing case for save_aux_ptr_type(). I wonder if we should pull the save_aux_ptr_type() call from it's current positions to do_check_insn() itself. ... ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH bpf-next 2/2] selftests/bpf: Cover mixed arena and map-value atomics 2026-08-13 12:01 [PATCH bpf-next 0/2] bpf: Reject mixed arena and ordinary atomic paths Yiyang Chen 2026-08-13 12:01 ` [PATCH bpf-next 1/2] bpf: Check pointer type for all atomic RMW paths Yiyang Chen @ 2026-08-13 12:01 ` Yiyang Chen 2026-08-13 13:03 ` bot+bpf-ci 2026-08-13 22:20 ` Eduard Zingerman 1 sibling, 2 replies; 6+ messages in thread From: Yiyang Chen @ 2026-08-13 12:01 UTC (permalink / raw) To: Alexei Starovoitov, Daniel Borkmann, John Fastabend, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai, Shuah Khan Cc: bpf, linux-kernel, linux-kselftest, Yiyang Chen Add a verifier test with one atomic RMW instruction reached through PTR_TO_ARENA and PTR_TO_MAP_VALUE paths. The verifier must reject the shared instruction with the existing incompatible-pointer diagnostic. Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn> --- tools/testing/selftests/bpf/progs/verifier_arena.c | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tools/testing/selftests/bpf/progs/verifier_arena.c b/tools/testing/selftests/bpf/progs/verifier_arena.c index b241bbcf54a8a..2e43da188194b 100644 --- a/tools/testing/selftests/bpf/progs/verifier_arena.c +++ b/tools/testing/selftests/bpf/progs/verifier_arena.c @@ -25,6 +25,15 @@ struct { __ulong(map_extra, ARENA_VM_START); /* start of mmap() region */ } arena SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, __u32); + __type(value, __u64); +} atomic_map SEC(".maps"); + +static __u64 arena_atomic_target SEC(".addr_space.1"); + SEC("socket") __success __retval(0) int basic_alloc1_nosleep(void *ctx) @@ -637,6 +646,41 @@ int non_arena_ptr_add_to_arena_ptr(void *ctx) #endif +SEC("socket") +__description("arena and map value atomic at the same instruction") +__failure __msg("same insn cannot be used with different pointers") +__arch_x86_64 +__load_if_JITed() +__naked void mixed_arena_map_value_atomic(void) +{ + asm volatile (" \ + r1 = 0; \ + *(u32 *)(r10 - 4) = r1; \ + r2 = r10; \ + r2 += -4; \ + r1 = %[atomic_map] ll; \ + call %[bpf_map_lookup_elem]; \ + if r0 == 0 goto 1f; \ + r6 = r0; \ + r7 = %[arena_atomic_target] ll; \ + .byte 0xbf; .byte 0x77; .short 1; .long 1; \ + call %[bpf_get_prandom_u32]; \ + if w0 != 0 goto 2f; \ + r8 = r6; \ + goto 3f; \ +2: r8 = r7; \ +3: r9 = 1; \ + lock *(u64 *)(r8 + 0) += r9; \ +1: r0 = 0; \ + exit; \ +" : + : __imm_addr(atomic_map), + __imm_addr(arena_atomic_target), + __imm(bpf_map_lookup_elem), + __imm(bpf_get_prandom_u32) + : __clobber_all); +} + static __noinline u32 __arena *check_arena_arg_nonglobal(u32 __arena *arg) { -- 2.43.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next 2/2] selftests/bpf: Cover mixed arena and map-value atomics 2026-08-13 12:01 ` [PATCH bpf-next 2/2] selftests/bpf: Cover mixed arena and map-value atomics Yiyang Chen @ 2026-08-13 13:03 ` bot+bpf-ci 2026-08-13 22:20 ` Eduard Zingerman 1 sibling, 0 replies; 6+ messages in thread From: bot+bpf-ci @ 2026-08-13 13:03 UTC (permalink / raw) To: chenyy23, ast, daniel, john.fastabend, andrii, eddyz87, memxor, martin.lau, song, yonghong.song, jolsa, emil, ihor.solodrai, shuah Cc: bpf, linux-kernel, linux-kselftest, chenyy23, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai [-- Attachment #1: Type: text/plain, Size: 3348 bytes --] > diff --git a/tools/testing/selftests/bpf/progs/verifier_arena.c b/tools/testing/selftests/bpf/progs/verifier_arena.c > index b241bbcf54a8a..2e43da188194b 100644 > --- a/tools/testing/selftests/bpf/progs/verifier_arena.c > +++ b/tools/testing/selftests/bpf/progs/verifier_arena.c > @@ -25,6 +25,15 @@ struct { > __ulong(map_extra, ARENA_VM_START); /* start of mmap() region */ > } arena SEC(".maps"); > > +struct { > + __uint(type, BPF_MAP_TYPE_ARRAY); > + __uint(max_entries, 1); > + __type(key, __u32); > + __type(value, __u64); > +} atomic_map SEC(".maps"); > + > +static __u64 arena_atomic_target SEC(".addr_space.1"); ^^^^^^^^^^^^^^^^^^^^ Does this arena global permanently consume one of the arena's two pages and break the existing allocation tests in this file? The arena is declared with max_entries = 2 (two pages). When libbpf loads the object, it places .addr_space.1 globals at the end of the arena: obj->arena_data_off = bpf_map_mmap_sz(arena_map) - roundup(arena_data_sz, PAGE_SIZE) = 2*4096 - 4096 = 4096 Then it copies the globals with: memcpy(map->mmaped + obj->arena_data_off, obj->arena_data, obj->arena_data_sz) That user-space write faults page 1. In arena_vm_fault(), the kernel calls: range_tree_clear(&arena->rt, vmf->pgoff, 1) marking page 1 as allocated and unavailable to bpf_arena_alloc_pages(). This happens during bpf_object__load() for every subtest since test_loader reopens and reloads the object each time. So every subtest now has 1 free page instead of 2. Looking at the existing tests that should fail: basic_alloc1_nosleep() / basic_alloc1(): second bpf_arena_alloc_pages(&arena, NULL, 1, ...) returns NULL -> return 2 basic_alloc2_nosleep() / basic_alloc2(): bpf_arena_alloc_pages(&arena, NULL, 2, ...) cannot find 2 contiguous free pages -> return 1 basic_alloc3_nosleep() / basic_alloc3(): allocates ar->map.max_entries (== 2) pages -> NULL -> return 1 basic_reserve1_nosleep() / basic_reserve1(): bpf_arena_reserve_pages() on the second page hits is_range_tree_set() == -ESRCH -> arena_reserve_pages() returns -EBUSY -> return 2 free_scalar_below_arena(): second alloc returns NULL -> return 2 All nine of these are annotated __success __retval(0) but would now return non-zero. verifier_arena_globals1.c is the existing precedent: it sizes the arena large and reserves a dedicated 16-page region for globals, and its check_reserve1() asserts that bpf_arena_reserve_pages() over the globals region fails because libbpf already mapped them in. The new test doesn't need an arena global at all. The idiomatic way to get a PTR_TO_ARENA in a __naked test is to call bpf_arena_alloc_pages() and use addr_space_cast(), as verifier_ldsx.c and compute_live_registers.c do. That links the arena to the program without adding arena data. Alternatively, could the arena's max_entries be grown and the page-count expectations of the existing tests updated? > + > SEC("socket") > __success __retval(0) > int basic_alloc1_nosleep(void *ctx) [ ... ] --- AI reviewed your patch. Please fix the bug or email reply why it's not a bug. See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md CI run summary: https://github.com/kernel-patches/bpf/actions/runs/31699396501 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next 2/2] selftests/bpf: Cover mixed arena and map-value atomics 2026-08-13 12:01 ` [PATCH bpf-next 2/2] selftests/bpf: Cover mixed arena and map-value atomics Yiyang Chen 2026-08-13 13:03 ` bot+bpf-ci @ 2026-08-13 22:20 ` Eduard Zingerman 1 sibling, 0 replies; 6+ messages in thread From: Eduard Zingerman @ 2026-08-13 22:20 UTC (permalink / raw) To: Yiyang Chen, Alexei Starovoitov, Daniel Borkmann, John Fastabend, Andrii Nakryiko, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai, Shuah Khan Cc: bpf, linux-kernel, linux-kselftest On Thu, 2026-08-13 at 12:01 +0000, Yiyang Chen wrote: > Add a verifier test with one atomic RMW instruction reached through > PTR_TO_ARENA and PTR_TO_MAP_VALUE paths. The verifier must reject the > shared instruction with the existing incompatible-pointer diagnostic. > > Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn> > --- > tools/testing/selftests/bpf/progs/verifier_arena.c | 44 ++++++++++++++++++++++ > 1 file changed, 44 insertions(+) > > diff --git a/tools/testing/selftests/bpf/progs/verifier_arena.c b/tools/testing/selftests/bpf/progs/verifier_arena.c > index b241bbcf54a8a..2e43da188194b 100644 > --- a/tools/testing/selftests/bpf/progs/verifier_arena.c > +++ b/tools/testing/selftests/bpf/progs/verifier_arena.c > @@ -25,6 +25,15 @@ struct { > __ulong(map_extra, ARENA_VM_START); /* start of mmap() region */ > } arena SEC(".maps"); > > +struct { > + __uint(type, BPF_MAP_TYPE_ARRAY); > + __uint(max_entries, 1); > + __type(key, __u32); > + __type(value, __u64); > +} atomic_map SEC(".maps"); Please use existing arena map. > + > +static __u64 arena_atomic_target SEC(".addr_space.1"); The bot is right, verifier_arena tests are failing. Did you test this patch before sending? > SEC("socket") > __success __retval(0) > int basic_alloc1_nosleep(void *ctx) > @@ -637,6 +646,41 @@ int non_arena_ptr_add_to_arena_ptr(void *ctx) > > #endif > > +SEC("socket") > +__description("arena and map value atomic at the same instruction") > +__failure __msg("same insn cannot be used with different pointers") > +__arch_x86_64 > +__load_if_JITed() > +__naked void mixed_arena_map_value_atomic(void) > +{ > + asm volatile (" \ > + r1 = 0; \ > + *(u32 *)(r10 - 4) = r1; \ > + r2 = r10; \ > + r2 += -4; \ > + r1 = %[atomic_map] ll; \ > + call %[bpf_map_lookup_elem]; \ > + if r0 == 0 goto 1f; \ > + r6 = r0; \ > + r7 = %[arena_atomic_target] ll; \ > + .byte 0xbf; .byte 0x77; .short 1; .long 1; \ Please use __imm_insn, see examples in the test suite. > + call %[bpf_get_prandom_u32]; \ > + if w0 != 0 goto 2f; \ > + r8 = r6; \ > + goto 3f; \ > +2: r8 = r7; \ > +3: r9 = 1; \ > + lock *(u64 *)(r8 + 0) += r9; \ > +1: r0 = 0; \ > + exit; \ > +" : > + : __imm_addr(atomic_map), > + __imm_addr(arena_atomic_target), You can conjure an arena pointer as in non_arena_ptr_add_to_arena_ptr() w/o the need for the variable. > + __imm(bpf_map_lookup_elem), > + __imm(bpf_get_prandom_u32) > + : __clobber_all); > +} > + > static __noinline > u32 __arena *check_arena_arg_nonglobal(u32 __arena *arg) > { pw-bot: cr. ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-13 22:21 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-08-13 12:01 [PATCH bpf-next 0/2] bpf: Reject mixed arena and ordinary atomic paths Yiyang Chen 2026-08-13 12:01 ` [PATCH bpf-next 1/2] bpf: Check pointer type for all atomic RMW paths Yiyang Chen 2026-08-13 22:12 ` Eduard Zingerman 2026-08-13 12:01 ` [PATCH bpf-next 2/2] selftests/bpf: Cover mixed arena and map-value atomics Yiyang Chen 2026-08-13 13:03 ` bot+bpf-ci 2026-08-13 22:20 ` Eduard Zingerman
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®