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