mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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

* [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 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

* 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®