mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH bpf-next v2 0/2] bpf: Preserve untrusted memory pointer type on scalar add
@ 2026-06-13 12:38 Nuoqi Gui
  2026-06-13 12:38 ` [PATCH bpf-next v2 1/2] " Nuoqi Gui
  2026-06-13 12:38 ` [PATCH bpf-next v2 2/2] selftests/bpf: Cover scalar add from rdonly untrusted memory Nuoqi Gui
  0 siblings, 2 replies; 5+ messages in thread
From: Nuoqi Gui @ 2026-06-13 12:38 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: Eduard Zingerman, Kumar Kartikeya Dwivedi, John Fastabend,
	Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Shuah Khan,
	bpf, linux-kernel, linux-kselftest, Nuoqi Gui

scalar += rdonly_untrusted_mem reaches adjust_ptr_min_max_vals() with the
pointer as the source register. The untrusted PTR_TO_MEM case returns there
without updating the scalar destination, leaving stale verifier state.

Update the destination before taking the untrusted PTR_TO_MEM early return.
ADD and pointer -= scalar keep the existing "do not track offsets" rule for
untrusted memory, while scalar -= pointer and unsupported pointer ALU
operations remain rejected instead of being accepted through the early return.

Patch 1 fixes the untrusted PTR_TO_MEM ALU early return. Patch 2 adds
verifier regression tests for scalar +=, scalar -=, and scalar ^= with
bpf_rdonly_cast(..., 0).

v1->v2:
  - Preserve the untrusted pointer state for scalar += pointer instead of
    rejecting the addition.
  - Reject scalar -= pointer and unsupported pointer ALU operations in the
    untrusted PTR_TO_MEM early return.
  - Update selftests for the new allowed-addition semantics and non-ADD ALU
    coverage.
v1: https://lore.kernel.org/bpf/20260609-f01-03-scalar-add-bpf-next-v1-0-e6212e274155@mails.tsinghua.edu.cn/

Validation:

  unpatched bpf-next 8496d9020ff3 with the new verifier cases:
    scalar_add_tracks_pointer: FAIL
      BPF_PROG_LOAD succeeded unexpectedly
    scalar_sub_ptr_not_ok: FAIL
      BPF_PROG_LOAD succeeded unexpectedly
    scalar_xor_ptr_not_ok: FAIL
      BPF_PROG_LOAD succeeded unexpectedly
    SUMMARY: FAIL

  patched bpf-next base 8496d9020ff3 + this series:
    scalar_add_tracks_pointer: PASS
      R1 bitwise operator &= on pointer prohibited
    scalar_sub_ptr_not_ok: PASS
      R1 tried to subtract pointer from scalar
    scalar_xor_ptr_not_ok: PASS
      R1 bitwise operator ^= on pointer prohibited
    SUMMARY: PASS

Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
Nuoqi Gui (2):
      bpf: Preserve untrusted memory pointer type on scalar add
      selftests/bpf: Cover scalar add from rdonly untrusted memory

 kernel/bpf/verifier.c                              | 28 +++++++++++-
 .../selftests/bpf/progs/mem_rdonly_untrusted.c     | 52 ++++++++++++++++++++++
 2 files changed, 78 insertions(+), 2 deletions(-)
---
base-commit: 8496d9020ff37a33c2a7b2fc84350fd03ffbde78
change-id: 20260610-f01-03-scalar-add-bpf-next-v2-0aaaa88499e9

Best regards,
--  
Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH bpf-next v2 1/2] bpf: Preserve untrusted memory pointer type on scalar add
  2026-06-13 12:38 [PATCH bpf-next v2 0/2] bpf: Preserve untrusted memory pointer type on scalar add Nuoqi Gui
@ 2026-06-13 12:38 ` Nuoqi Gui
  2026-06-22  0:50   ` Alexei Starovoitov
  2026-06-13 12:38 ` [PATCH bpf-next v2 2/2] selftests/bpf: Cover scalar add from rdonly untrusted memory Nuoqi Gui
  1 sibling, 1 reply; 5+ messages in thread
From: Nuoqi Gui @ 2026-06-13 12:38 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: Eduard Zingerman, Kumar Kartikeya Dwivedi, John Fastabend,
	Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Shuah Khan,
	bpf, linux-kernel, linux-kselftest, Nuoqi Gui

scalar += rdonly_untrusted_mem reaches adjust_ptr_min_max_vals() with the
pointer as the source register. The untrusted PTR_TO_MEM case returns there
without updating the scalar destination, leaving stale verifier state.

Handle the untrusted PTR_TO_MEM case before the early return. Addition and
pointer-minus-scalar subtraction preserve the pointer type and keep the
existing "do not track offsets" rule for untrusted memory.
Scalar-minus-pointer and unsupported pointer ALU operations are still
rejected instead of being accepted by the early return.

Fixes: f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
 kernel/bpf/verifier.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index c8d980fdd709..26c67c53166b 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -13729,8 +13729,32 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
 	 * Accesses to untrusted PTR_TO_MEM are done through probe
 	 * instructions, hence no need to track offsets.
 	 */
-	if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type & PTR_UNTRUSTED))
-		return 0;
+	if (base_type(ptr_reg->type) == PTR_TO_MEM &&
+	    (ptr_reg->type & PTR_UNTRUSTED)) {
+		switch (opcode) {
+		case BPF_ADD:
+			*dst_reg = *ptr_reg;
+			return 0;
+		case BPF_SUB:
+			if (dst_reg == off_reg) {
+				verbose(env, "R%d tried to subtract pointer from scalar\n",
+					dst);
+				return -EACCES;
+			}
+			*dst_reg = *ptr_reg;
+			return 0;
+		case BPF_AND:
+		case BPF_OR:
+		case BPF_XOR:
+			verbose(env, "R%d bitwise operator %s on pointer prohibited\n",
+				dst, bpf_alu_string[opcode >> 4]);
+			return -EACCES;
+		default:
+			verbose(env, "R%d pointer arithmetic with %s operator prohibited\n",
+				dst, bpf_alu_string[opcode >> 4]);
+			return -EACCES;
+		}
+	}
 
 	switch (base_type(ptr_reg->type)) {
 	case PTR_TO_CTX:

-- 
2.34.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH bpf-next v2 2/2] selftests/bpf: Cover scalar add from rdonly untrusted memory
  2026-06-13 12:38 [PATCH bpf-next v2 0/2] bpf: Preserve untrusted memory pointer type on scalar add Nuoqi Gui
  2026-06-13 12:38 ` [PATCH bpf-next v2 1/2] " Nuoqi Gui
@ 2026-06-13 12:38 ` Nuoqi Gui
  2026-06-13 13:19   ` bot+bpf-ci
  1 sibling, 1 reply; 5+ messages in thread
From: Nuoqi Gui @ 2026-06-13 12:38 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: Eduard Zingerman, Kumar Kartikeya Dwivedi, John Fastabend,
	Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Shuah Khan,
	bpf, linux-kernel, linux-kselftest, Nuoqi Gui

Add a verifier test for scalar += rdonly_untrusted_mem. The program gets a
read-only untrusted memory value from bpf_rdonly_cast(..., 0), adds it to a
scalar destination, and then applies a bitwise operation to the result.

The addition itself is allowed, but the result must be tracked as a
pointer. The verifier should reject the following bitwise operation instead
of preserving stale scalar state.

Add coverage for scalar -= pointer and scalar ^= pointer as well. This
prevents the early return from bypassing normal pointer ALU rejection.

Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
 .../selftests/bpf/progs/mem_rdonly_untrusted.c     | 52 ++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/mem_rdonly_untrusted.c b/tools/testing/selftests/bpf/progs/mem_rdonly_untrusted.c
index 5b4453747c23..67633129ed41 100644
--- a/tools/testing/selftests/bpf/progs/mem_rdonly_untrusted.c
+++ b/tools/testing/selftests/bpf/progs/mem_rdonly_untrusted.c
@@ -77,6 +77,58 @@ int offset_not_tracked(void *ctx)
 	return s;
 }
 
+SEC("socket")
+__failure
+__msg("R1 bitwise operator &= on pointer prohibited")
+__naked void scalar_add_tracks_pointer(void)
+{
+	asm volatile ("r1 = 0;"
+	"r2 = 0;"
+	"call %[bpf_rdonly_cast];"
+	"r1 = 0;"
+	"r1 += r0;"
+	"r1 &= 1;"
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm(bpf_rdonly_cast)
+	: __clobber_all);
+}
+
+SEC("socket")
+__failure
+__msg("R1 tried to subtract pointer from scalar")
+__naked void scalar_sub_ptr_not_ok(void)
+{
+	asm volatile ("r1 = 0;"
+	"r2 = 0;"
+	"call %[bpf_rdonly_cast];"
+	"r1 = 0;"
+	"r1 -= r0;"
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm(bpf_rdonly_cast)
+	: __clobber_all);
+}
+
+SEC("socket")
+__failure
+__msg("R1 bitwise operator ^= on pointer prohibited")
+__naked void scalar_xor_ptr_not_ok(void)
+{
+	asm volatile ("r1 = 0;"
+	"r2 = 0;"
+	"call %[bpf_rdonly_cast];"
+	"r1 = 0;"
+	"r1 ^= r0;"
+	"r0 = 0;"
+	"exit;"
+	:
+	: __imm(bpf_rdonly_cast)
+	: __clobber_all);
+}
+
 SEC("socket")
 __failure
 __msg("cannot write into rdonly_untrusted_mem")

-- 
2.34.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next v2 2/2] selftests/bpf: Cover scalar add from rdonly untrusted memory
  2026-06-13 12:38 ` [PATCH bpf-next v2 2/2] selftests/bpf: Cover scalar add from rdonly untrusted memory Nuoqi Gui
@ 2026-06-13 13:19   ` bot+bpf-ci
  0 siblings, 0 replies; 5+ messages in thread
From: bot+bpf-ci @ 2026-06-13 13:19 UTC (permalink / raw)
  To: gnq25, ast, daniel, andrii
  Cc: eddyz87, memxor, john.fastabend, martin.lau, song, yonghong.song,
	jolsa, shuah, bpf, linux-kernel, linux-kselftest, gnq25, ast,
	andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
	ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 1369 bytes --]

> selftests/bpf: Cover scalar add from rdonly untrusted memory
>
> Add a verifier test for scalar += rdonly_untrusted_mem. The program gets a
> read-only untrusted memory value from bpf_rdonly_cast(..., 0), adds it to a
> scalar destination, and then applies a bitwise operation to the result.
>
> The addition itself is allowed, but the result must be tracked as a
> pointer. The verifier should reject the following bitwise operation instead
> of preserving stale scalar state.
>
> Add coverage for scalar -= pointer and scalar ^= pointer as well. This
> prevents the early return from bypassing normal pointer ALU rejection.
>
> Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>

This selftest covers the early return in adjust_ptr_min_max_vals() that left
stale scalar state on the destination for scalar += rdonly_untrusted_mem,
which could let a later pointer ALU operation be accepted. That early return
came in with f2362a57aeff, and the companion functional fix carries a
Fixes: tag, but this selftest commit does not.

Should this include:

  Fixes: f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")


---
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/27467222513

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next v2 1/2] bpf: Preserve untrusted memory pointer type on scalar add
  2026-06-13 12:38 ` [PATCH bpf-next v2 1/2] " Nuoqi Gui
@ 2026-06-22  0:50   ` Alexei Starovoitov
  0 siblings, 0 replies; 5+ messages in thread
From: Alexei Starovoitov @ 2026-06-22  0:50 UTC (permalink / raw)
  To: Nuoqi Gui
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, John Fastabend,
	Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Shuah Khan,
	bpf, LKML, open list:KERNEL SELFTEST FRAMEWORK

On Sat, Jun 13, 2026 at 5:38 AM Nuoqi Gui <gnq25@mails.tsinghua.edu.cn> wrote:
>
> scalar += rdonly_untrusted_mem reaches adjust_ptr_min_max_vals() with the
> pointer as the source register. The untrusted PTR_TO_MEM case returns there
> without updating the scalar destination, leaving stale verifier state.
>
> Handle the untrusted PTR_TO_MEM case before the early return. Addition and
> pointer-minus-scalar subtraction preserve the pointer type and keep the
> existing "do not track offsets" rule for untrusted memory.
> Scalar-minus-pointer and unsupported pointer ALU operations are still
> rejected instead of being accepted by the early return.
>
> Fixes: f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")
> Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
> ---
>  kernel/bpf/verifier.c | 28 ++++++++++++++++++++++++++--
>  1 file changed, 26 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index c8d980fdd709..26c67c53166b 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -13729,8 +13729,32 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
>          * Accesses to untrusted PTR_TO_MEM are done through probe
>          * instructions, hence no need to track offsets.
>          */
> -       if (base_type(ptr_reg->type) == PTR_TO_MEM && (ptr_reg->type & PTR_UNTRUSTED))
> -               return 0;
> +       if (base_type(ptr_reg->type) == PTR_TO_MEM &&
> +           (ptr_reg->type & PTR_UNTRUSTED)) {

do not introduce line wrap.

> +               switch (opcode) {
> +               case BPF_ADD:
> +                       *dst_reg = *ptr_reg;
> +                       return 0;
> +               case BPF_SUB:
> +                       if (dst_reg == off_reg) {
> +                               verbose(env, "R%d tried to subtract pointer from scalar\n",
> +                                       dst);
> +                               return -EACCES;
> +                       }
> +                       *dst_reg = *ptr_reg;
> +                       return 0;
> +               case BPF_AND:
> +               case BPF_OR:
> +               case BPF_XOR:
> +                       verbose(env, "R%d bitwise operator %s on pointer prohibited\n",
> +                               dst, bpf_alu_string[opcode >> 4]);
> +                       return -EACCES;
> +               default:
> +                       verbose(env, "R%d pointer arithmetic with %s operator prohibited\n",
> +                               dst, bpf_alu_string[opcode >> 4]);
> +                       return -EACCES;

No need to arbitrary rejection.
All ALUs should be allowed.
Something like
if (ptr_reg != dst_reg)
  *dst_reg = *ptr_reg;

pw-bot: cr

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-06-22  0:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-13 12:38 [PATCH bpf-next v2 0/2] bpf: Preserve untrusted memory pointer type on scalar add Nuoqi Gui
2026-06-13 12:38 ` [PATCH bpf-next v2 1/2] " Nuoqi Gui
2026-06-22  0:50   ` Alexei Starovoitov
2026-06-13 12:38 ` [PATCH bpf-next v2 2/2] selftests/bpf: Cover scalar add from rdonly untrusted memory Nuoqi Gui
2026-06-13 13:19   ` bot+bpf-ci

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®