[PATCH bpf-next v2 2/2] selftests/bpf: Cover scalar add from rdonly untrusted memory

From: Nuoqi Gui

Date: Sat Jun 13 2026 - 08:40:07 EST


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@xxxxxxxxxxxxxxxxxxxxx>
---
.../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