BPF List
 help / color / mirror / Atom feed
* [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls
@ 2026-09-05  0:05 Eduard Zingerman
  2026-09-05  0:05 ` [PATCH bpf 01/10] bpf: mark a NULL call argument precise Eduard Zingerman
                   ` (10 more replies)
  0 siblings, 11 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:05 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

Fix [1] uncovered a host of locations where the call to
bpf_register_is_null() is not followed by a call to
bpf_mark_chain_precision().

check_map_kptr_access() is omitted as it is handled [2]
by another series.

[1] https://lore.kernel.org/bpf/20260904083325.2083493-7-eddyz87@gmail.com/
[2] https://lore.kernel.org/bpf/20260904104203.345917-6-memxor@gmail.com/

---
Eduard Zingerman (10):
      bpf: mark a NULL call argument precise
      selftests/bpf: precision of a NULL helper argument
      bpf: mark a NULL memory argument of a call precise
      selftests/bpf: precision of a NULL global subprogram memory argument
      bpf: mark a NULL kfunc argument precise
      selftests/bpf: precision of a NULL kfunc argument
      bpf: mark a NULL BTF_ID argument of a global subprogram precise
      selftests/bpf: precision of a NULL global subprogram BTF_ID argument
      bpf: propagate mark_chain_precision() errors out of loop_flag_is_zero()
      bpf: use mark_arg_precision() in check_mem_size_reg()

 kernel/bpf/verifier.c                              |  78 +++++++++++-----
 .../selftests/bpf/progs/verifier_cgroup_storage.c  |  29 ++++++
 .../selftests/bpf/progs/verifier_global_ptr_args.c |  24 +++++
 .../selftests/bpf/progs/verifier_precision.c       | 100 +++++++++++++++++++++
 .../bpf/progs/verifier_subprog_precision.c         |  12 +--
 5 files changed, 214 insertions(+), 29 deletions(-)
---
base-commit: 41e6f03658adfa9df68642750b53a046f1abdea9
change-id: 20260904-register-is-null-precise-fixes-15c7f8cd7a73

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

* [PATCH bpf 01/10] bpf: mark a NULL call argument precise
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
@ 2026-09-05  0:05 ` Eduard Zingerman
  2026-09-05  0:21   ` sashiko-bot
  2026-09-05  0:05 ` [PATCH bpf 02/10] selftests/bpf: precision of a NULL helper argument Eduard Zingerman
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:05 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

check_func_arg() allows bpf_register_is_null() for nullable arguments
w/o marking the underlying scalar register precise. Hence a checkpoint
created on such a path would prune against arbitrary scalar value.

check_helper_call() enforces second parameter of the
bpf_get_local_storage() to be zero, w/o marking the underlying scalar
register precise. Hence a checkpoint created on such a path would
prune against arbitrary scalar value.

Grouping these two into one patch, as they share the same fixes tag.

Fixes: b5dc0163d8fd ("bpf: precise scalar_value tracking")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 kernel/bpf/verifier.c                                        |  9 ++++++++-
 .../testing/selftests/bpf/progs/verifier_subprog_precision.c | 12 ++++++------
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 9c6ad157a61e..ca362a7ea58c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -8752,11 +8752,15 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
 			return err;
 	}
 
-	if (bpf_register_is_null(reg) && type_may_be_null(arg_type))
+	if (bpf_register_is_null(reg) && type_may_be_null(arg_type)) {
 		/* A NULL register has a SCALAR_VALUE type, so skip
 		 * type checking.
 		 */
+		err = mark_chain_precision(env, regno);
+		if (err)
+			return err;
 		goto skip_type_check;
+	}
 
 	/* arg_btf_id and arg_size are in a union. */
 	if (base_type(arg_type) == ARG_PTR_TO_BTF_ID ||
@@ -10906,6 +10910,9 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 			verbose(env, "get_local_storage() doesn't support non-zero flags\n");
 			return -EINVAL;
 		}
+		err = mark_chain_precision(env, BPF_REG_2);
+		if (err)
+			return err;
 		break;
 	case BPF_FUNC_for_each_map_elem:
 		err = push_callback_call(env, insn, insn_idx, meta.subprogno,
diff --git a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
index e174a905c562..dc0c7034c04f 100644
--- a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
+++ b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
@@ -287,9 +287,9 @@ __msg("17: (b7) r0 = 0")
 __msg("18: (95) exit")
 __msg("returning from callee:")
 __msg("to caller at 9:")
-__msg("frame 0: propagating r1,r4")
+__msg("frame 0: propagating r1,r3,r4")
 __msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
-__msg("mark_precise: frame0: regs=r1,r4 stack= before 18: (95) exit")
+__msg("mark_precise: frame0: regs=r1,r3,r4 stack= before 18: (95) exit")
 __msg("from 18 to 9: safe")
 __naked int callback_result_precise(void)
 {
@@ -419,9 +419,9 @@ __msg("to caller at 9:")
 /* r1, r4 are always precise for bpf_loop(),
  * r6 was marked before backtracking to callback body.
  */
-__msg("frame 0: propagating r1,r4,r6")
+__msg("frame 0: propagating r1,r3,r4,r6")
 __msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
-__msg("mark_precise: frame0: regs=r1,r4,r6 stack= before 16: (95) exit")
+__msg("mark_precise: frame0: regs=r1,r3,r4,r6 stack= before 16: (95) exit")
 __msg("mark_precise: frame1: regs= stack= before 15: (b7) r0 = 0")
 __msg("mark_precise: frame1: regs= stack= before 9: (85) call bpf_loop")
 __msg("mark_precise: frame0: parent state regs= stack=:")
@@ -575,9 +575,9 @@ __msg("to caller at 10:")
 /* r1, r4 are always precise for bpf_loop(),
  * fp-8 was marked before backtracking to callback body.
  */
-__msg("frame 0: propagating r1,r4,fp-8")
+__msg("frame 0: propagating r1,r3,r4,fp-8")
 __msg("mark_precise: frame0: last_idx 10 first_idx 10 subseq_idx -1")
-__msg("mark_precise: frame0: regs=r1,r4 stack=-8 before 18: (95) exit")
+__msg("mark_precise: frame0: regs=r1,r3,r4 stack=-8 before 18: (95) exit")
 __msg("mark_precise: frame1: regs= stack= before 17: (b7) r0 = 0")
 __msg("mark_precise: frame1: regs= stack= before 10: (85) call bpf_loop#181")
 __msg("mark_precise: frame0: parent state regs= stack=:")

-- 
2.55.0

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

* [PATCH bpf 02/10] selftests/bpf: precision of a NULL helper argument
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
  2026-09-05  0:05 ` [PATCH bpf 01/10] bpf: mark a NULL call argument precise Eduard Zingerman
@ 2026-09-05  0:05 ` Eduard Zingerman
  2026-09-05  0:05 ` [PATCH bpf 03/10] bpf: mark a NULL memory argument of a call precise Eduard Zingerman
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:05 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

Check that mark_chain_precision() is called for a NULL nullable memory
argument and for the zero flags argument of bpf_get_local_storage().

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 .../selftests/bpf/progs/verifier_cgroup_storage.c  | 29 ++++++++++++++++++
 .../selftests/bpf/progs/verifier_precision.c       | 34 ++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/verifier_cgroup_storage.c b/tools/testing/selftests/bpf/progs/verifier_cgroup_storage.c
index 9a13f5c11ac7..884080a5bffc 100644
--- a/tools/testing/selftests/bpf/progs/verifier_cgroup_storage.c
+++ b/tools/testing/selftests/bpf/progs/verifier_cgroup_storage.c
@@ -305,4 +305,33 @@ __naked void cpu_cgroup_storage_access_6(void)
 	: __clobber_all);
 }
 
+/*
+ * Verification takes two paths: with r2 being scalar zero on path (1)
+ * and with r2 being some other scalar on path (2).
+ * Check that the verifier does not use checkpoints created
+ * on path (1) to prune path (2).
+ */
+SEC("cgroup/skb")
+__failure
+__flag(BPF_F_TEST_STATE_FREQ)
+__msg("get_local_storage() doesn't support non-zero flags")
+__naked void non_zero_flags_on_a_pruned_path(void)
+{
+	asm volatile ("					\
+	call %[bpf_get_prandom_u32];			\
+	/* r2 is 0 on the path explored first, 1 on the other */\
+	r2 = 1;						\
+	if r0 == 0 goto 1f;				\
+	r2 = 0;						\
+1:	r1 = %[cgroup_storage] ll;			\
+	call %[bpf_get_local_storage];			\
+	r0 = 0;						\
+	exit;						\
+"	:
+	: __imm(bpf_get_prandom_u32),
+	  __imm(bpf_get_local_storage),
+	  __imm_addr(cgroup_storage)
+	: __clobber_all);
+}
+
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools/testing/selftests/bpf/progs/verifier_precision.c
index 6f325876efdd..3e290b07f672 100644
--- a/tools/testing/selftests/bpf/progs/verifier_precision.c
+++ b/tools/testing/selftests/bpf/progs/verifier_precision.c
@@ -642,4 +642,38 @@ __naked int bpf_atomic_cmpxchg_32bit_precision(void)
 	: __clobber_all);
 }
 
+/*
+ * Verification takes two paths: with r1 being scalar zero on path (1)
+ * and with r1 being some other scalar on path (2).
+ * Check that the verifier does not use checkpoints created
+ * on path (1) to prune path (2).
+ */
+SEC("?tc")
+__flag(BPF_F_TEST_STATE_FREQ)
+__failure __msg("R1 type=scalar expected=fp")
+__naked int null_mem_arg_zero_size(void)
+{
+	asm volatile (
+		"call %[bpf_get_prandom_u32];"
+		"r1 = 42;"
+		"if r0 > 42 goto 1f;"
+		"r1 = 0;"
+	"1:"
+		"r2 = 0;"
+		"r3 = 0;"
+		"r4 = 0;"
+		"r5 = 0;"
+		/*
+		 * ARG_PTR_TO_MEM | PTR_MAYBE_NULL parameter can be NULL,
+		 * but can't be some other scalar value.
+		 */
+		"call %[bpf_csum_diff];"
+		"r0 = 0;"
+		"exit;"
+		:
+		: __imm(bpf_get_prandom_u32),
+		  __imm(bpf_csum_diff)
+		: __clobber_all);
+}
+
 char _license[] SEC("license") = "GPL";

-- 
2.55.0

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

* [PATCH bpf 03/10] bpf: mark a NULL memory argument of a call precise
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
  2026-09-05  0:05 ` [PATCH bpf 01/10] bpf: mark a NULL call argument precise Eduard Zingerman
  2026-09-05  0:05 ` [PATCH bpf 02/10] selftests/bpf: precision of a NULL helper argument Eduard Zingerman
@ 2026-09-05  0:05 ` Eduard Zingerman
  2026-09-05  0:23   ` sashiko-bot
  2026-09-05  0:51   ` bot+bpf-ci
  2026-09-05  0:05 ` [PATCH bpf 04/10] selftests/bpf: precision of a NULL global subprogram memory argument Eduard Zingerman
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:05 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

check_mem_reg() allows bpf_register_is_null() for nullable arguments
w/o marking the underlying scalar register precise. Hence a checkpoint
created on such a path would prune against arbitrary scalar value.

The argument may live on the stack rather than in a register when a
call has more than MAX_BPF_FUNC_REG_ARGS arguments, hence the new
mark_arg_precision() helper.

Fixes: e5069b9c23b3 ("bpf: Support pointers in global func args")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 kernel/bpf/verifier.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index ca362a7ea58c..b758f2822754 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -4246,6 +4246,15 @@ static int mark_stack_arg_precision(struct bpf_verifier_env *env, int arg_idx)
 	return mark_chain_precision_batch(env, env->cur_state);
 }
 
+static int mark_arg_precision(struct bpf_verifier_env *env, argno_t argno)
+{
+	int regno = reg_from_argno(argno);
+
+	if (regno >= 0)
+		return mark_chain_precision(env, regno);
+	return mark_stack_arg_precision(env, arg_idx_from_argno(argno));
+}
+
 static int check_outgoing_stack_args(struct bpf_verifier_env *env, struct bpf_func_state *caller,
 				     int nargs, const char *callee_name, const struct btf *btf,
 				     const struct btf_param *args)
@@ -7168,7 +7177,7 @@ static int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg
 	int size, err = 0;
 
 	if (bpf_register_is_null(reg))
-		return 0;
+		return mark_arg_precision(env, argno);
 	if (known_memory)
 		*known_memory = true;
 

-- 
2.55.0

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

* [PATCH bpf 04/10] selftests/bpf: precision of a NULL global subprogram memory argument
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
                   ` (2 preceding siblings ...)
  2026-09-05  0:05 ` [PATCH bpf 03/10] bpf: mark a NULL memory argument of a call precise Eduard Zingerman
@ 2026-09-05  0:05 ` Eduard Zingerman
  2026-09-05  0:51   ` bot+bpf-ci
  2026-09-05  0:05 ` [PATCH bpf 05/10] bpf: mark a NULL kfunc argument precise Eduard Zingerman
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:05 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

Check that mark_chain_precision() is called for a NULL pointer passed
as a nullable pointer argument of a global subprogram.
(Pointer arguments of the global subprograms are nullable by default).

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 .../selftests/bpf/progs/verifier_precision.c       | 32 ++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools/testing/selftests/bpf/progs/verifier_precision.c
index 3e290b07f672..fb7dfa1246ef 100644
--- a/tools/testing/selftests/bpf/progs/verifier_precision.c
+++ b/tools/testing/selftests/bpf/progs/verifier_precision.c
@@ -676,4 +676,36 @@ __naked int null_mem_arg_zero_size(void)
 		: __clobber_all);
 }
 
+__weak int subprog_mem_arg(int *p)
+{
+	if (p)
+		return *p;
+	return 0;
+}
+
+/*
+ * Verification takes two paths: with r1 being scalar zero on path (1)
+ * and with r1 being some other scalar on path (2).
+ * Check that the verifier does not use checkpoints created
+ * on path (1) to prune path (2).
+ */
+SEC("?raw_tp")
+__flag(BPF_F_TEST_STATE_FREQ)
+__failure __msg("R1 type=scalar expected=fp")
+__naked int null_mem_arg_global_subprog(void)
+{
+	asm volatile (
+		"call %[bpf_get_prandom_u32];"
+		"r1 = 42;"
+		"if r0 > 42 goto 1f;"
+		"r1 = 0;"
+	"1:"
+		"call subprog_mem_arg;"
+		"r0 = 0;"
+		"exit;"
+		:
+		: __imm(bpf_get_prandom_u32)
+		: __clobber_all);
+}
+
 char _license[] SEC("license") = "GPL";

-- 
2.55.0

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

* [PATCH bpf 05/10] bpf: mark a NULL kfunc argument precise
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
                   ` (3 preceding siblings ...)
  2026-09-05  0:05 ` [PATCH bpf 04/10] selftests/bpf: precision of a NULL global subprogram memory argument Eduard Zingerman
@ 2026-09-05  0:05 ` Eduard Zingerman
  2026-09-05  0:51   ` bot+bpf-ci
  2026-09-05  0:05 ` [PATCH bpf 06/10] selftests/bpf: precision of a NULL kfunc argument Eduard Zingerman
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:05 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

check_kfunc_arg() allows bpf_register_is_null() for nullable arguments
w/o marking the underlying scalar register precise. Hence a checkpoint
created on such a path would prune against arbitrary scalar value.

Fixes: 3bda08b63670 ("bpf: Allow NULL buffers in bpf_dynptr_slice(_rw)")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 kernel/bpf/verifier.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index b758f2822754..2b3d08097806 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -12716,8 +12716,12 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me
 		if (reg_is_referenced(env, reg))
 			update_ref_obj(&meta->ref_obj, reg);
 
-		if (bpf_register_is_null(reg) && type_may_be_null(kf_arg_type))
+		if (bpf_register_is_null(reg) && type_may_be_null(kf_arg_type)) {
+			ret = mark_arg_precision(env, argno);
+			if (ret)
+				return ret;
 			continue;
+		}
 
 		if (is_kfunc_arg_map(btf, &args[i])) {
 			ref_id = *reg2btf_ids[CONST_PTR_TO_MAP];

-- 
2.55.0

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

* [PATCH bpf 06/10] selftests/bpf: precision of a NULL kfunc argument
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
                   ` (4 preceding siblings ...)
  2026-09-05  0:05 ` [PATCH bpf 05/10] bpf: mark a NULL kfunc argument precise Eduard Zingerman
@ 2026-09-05  0:05 ` Eduard Zingerman
  2026-09-05  0:05 ` [PATCH bpf 07/10] bpf: mark a NULL BTF_ID argument of a global subprogram precise Eduard Zingerman
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:05 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

Check that mark_chain_precision() is called for a NULL pointer passed
as a __nullable kfunc memory argument.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 .../selftests/bpf/progs/verifier_precision.c       | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools/testing/selftests/bpf/progs/verifier_precision.c
index fb7dfa1246ef..f4459561bf39 100644
--- a/tools/testing/selftests/bpf/progs/verifier_precision.c
+++ b/tools/testing/selftests/bpf/progs/verifier_precision.c
@@ -2,8 +2,10 @@
 /* Copyright (C) 2023 SUSE LLC */
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
+#include <stdbool.h>
 #include "../../../include/linux/filter.h"
 #include "bpf_misc.h"
+#include "bpf_kfuncs.h"
 
 struct {
 	__uint(type, BPF_MAP_TYPE_ARRAY);
@@ -708,4 +710,36 @@ __naked int null_mem_arg_global_subprog(void)
 		: __clobber_all);
 }
 
+/* Same as above, check that path with r3 == 0 does not prune the path with r3 != 0 */
+SEC("?tc")
+__flag(BPF_F_TEST_STATE_FREQ)
+__failure __msg("R3 type=scalar expected=fp")
+int null_kfunc_arg_dynptr_slice(struct __sk_buff *skb)
+{
+	struct bpf_dynptr ptr;
+
+	bpf_dynptr_from_skb(skb, 0, &ptr);
+	asm volatile (
+		"call %[bpf_get_prandom_u32];"
+		"r3 = 42;"
+		"if r0 > 42 goto 1f;"
+		"r3 = 0;"
+	"1:"
+		"r1 = %[ptr];"
+		"r2 = 0;"
+		"r4 = 8;"
+		"call %[bpf_dynptr_slice];"
+		:
+		: __imm_ptr(ptr),
+		  __imm(bpf_get_prandom_u32),
+		  __imm(bpf_dynptr_slice)
+		: __clobber_common);
+	return 0;
+}
+
+void __kfunc_btf_root(void)
+{
+	bpf_dynptr_slice(0, 0, 0, 0);
+}
+
 char _license[] SEC("license") = "GPL";

-- 
2.55.0

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

* [PATCH bpf 07/10] bpf: mark a NULL BTF_ID argument of a global subprogram precise
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
                   ` (5 preceding siblings ...)
  2026-09-05  0:05 ` [PATCH bpf 06/10] selftests/bpf: precision of a NULL kfunc argument Eduard Zingerman
@ 2026-09-05  0:05 ` Eduard Zingerman
  2026-09-05  0:19   ` sashiko-bot
  2026-09-05  0:05 ` [PATCH bpf 08/10] selftests/bpf: precision of a NULL global subprogram BTF_ID argument Eduard Zingerman
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:05 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

btf_check_func_arg_match() accepts a NULL register for an
ARG_PTR_TO_BTF_ID argument tagged __arg_nullable and skips
check_reg_type() and check_func_arg_reg_off() without marking the
register precise. Hence a checkpoint created on such a path would
prune against arbitrary scalar value.

Fixes: e2b3c4ff5d18 ("bpf: add __arg_trusted global func arg tag")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 kernel/bpf/verifier.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 2b3d08097806..3c3575215899 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -9767,8 +9767,12 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
 			struct bpf_call_arg_meta meta;
 			int err;
 
-			if (bpf_register_is_null(reg) && type_may_be_null(arg->arg_type))
+			if (bpf_register_is_null(reg) && type_may_be_null(arg->arg_type)) {
+				err = mark_arg_precision(env, argno);
+				if (err)
+					return err;
 				continue;
+			}
 
 			memset(&meta, 0, sizeof(meta)); /* leave func_id as zero */
 			err = check_reg_type(env, reg, argno, arg->arg_type, &arg->btf_id, &meta,

-- 
2.55.0

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

* [PATCH bpf 08/10] selftests/bpf: precision of a NULL global subprogram BTF_ID argument
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
                   ` (6 preceding siblings ...)
  2026-09-05  0:05 ` [PATCH bpf 07/10] bpf: mark a NULL BTF_ID argument of a global subprogram precise Eduard Zingerman
@ 2026-09-05  0:05 ` Eduard Zingerman
  2026-09-05  0:06 ` [PATCH bpf 09/10] bpf: propagate mark_chain_precision() errors out of loop_flag_is_zero() Eduard Zingerman
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:05 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

Check that mark_chain_precision() is called for a NULL pointer passed
as an __arg_trusted __arg_nullable argument of a global subprogram.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 .../selftests/bpf/progs/verifier_global_ptr_args.c | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c b/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c
index 0bdeb7bc4687..a3d2af8dc839 100644
--- a/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c
+++ b/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c
@@ -56,6 +56,30 @@ int trusted_task_arg_nullable(void *ctx)
 	return res;
 }
 
+/*
+ * Check that the verifier does not use checkpoints created
+ * on path with r1 == 0 to prune path with r1 != 0.
+ */
+SEC("?tp_btf/task_newtask")
+__failure
+__flag(BPF_F_TEST_STATE_FREQ)
+__msg("R1 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_")
+__naked int null_btf_id_arg_global_subprog(void)
+{
+	asm volatile (
+		"call %[bpf_get_prandom_u32];"
+		"r1 = 42;"
+		"if r0 > 42 goto 1f;"
+		"r1 = 0;"
+	"1:"
+		"call subprog_trusted_task_nullable;"
+		"r0 = 0;"
+		"exit;"
+		:
+		: __imm(bpf_get_prandom_u32)
+		: __clobber_all);
+}
+
 __weak int subprog_trusted_task_nonnull(struct task_struct *task __arg_trusted)
 {
 	return task->pid + task->tgid;

-- 
2.55.0

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

* [PATCH bpf 09/10] bpf: propagate mark_chain_precision() errors out of loop_flag_is_zero()
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
                   ` (7 preceding siblings ...)
  2026-09-05  0:05 ` [PATCH bpf 08/10] selftests/bpf: precision of a NULL global subprogram BTF_ID argument Eduard Zingerman
@ 2026-09-05  0:06 ` Eduard Zingerman
  2026-09-05  0:06 ` [PATCH bpf 10/10] bpf: use mark_arg_precision() in check_mem_size_reg() Eduard Zingerman
  2026-09-05  1:20 ` [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls patchwork-bot+netdevbpf
  10 siblings, 0 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:06 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

Stop verification if mark_chain_precision() fails when called from
loop_flag_is_zero(). No functional change intended for the paths where
backtracking succeeds.

Fixes: 1ade23711971 ("bpf: Inline calls to bpf_loop when callback is known")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 kernel/bpf/verifier.c | 36 +++++++++++++++++++++++++-----------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 3c3575215899..dc1fef1ef1ef 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -10685,33 +10685,45 @@ static struct bpf_insn_aux_data *cur_aux(const struct bpf_verifier_env *env)
 	return &env->insn_aux_data[env->insn_idx];
 }
 
-static bool loop_flag_is_zero(struct bpf_verifier_env *env)
+/* Returns 1 if R4 is a known zero, 0 if it is not, a negative errno on error. */
+static int loop_flag_is_zero(struct bpf_verifier_env *env)
 {
 	struct bpf_reg_state *reg = reg_state(env, BPF_REG_4);
-	bool reg_is_null = bpf_register_is_null(reg);
+	int err;
 
-	if (reg_is_null)
-		mark_chain_precision(env, BPF_REG_4);
+	if (!bpf_register_is_null(reg))
+		return 0;
 
-	return reg_is_null;
+	err = mark_chain_precision(env, BPF_REG_4);
+	if (err)
+		return err;
+	return 1;
 }
 
-static void update_loop_inline_state(struct bpf_verifier_env *env, u32 subprogno)
+static int update_loop_inline_state(struct bpf_verifier_env *env, u32 subprogno)
 {
 	struct bpf_loop_inline_state *state = &cur_aux(env)->loop_inline_state;
+	int flag_is_zero;
 
 	if (!state->initialized) {
+		flag_is_zero = loop_flag_is_zero(env);
+		if (flag_is_zero < 0)
+			return flag_is_zero;
 		state->initialized = 1;
-		state->fit_for_inline = loop_flag_is_zero(env);
+		state->fit_for_inline = flag_is_zero;
 		state->callback_subprogno = subprogno;
-		return;
+		return 0;
 	}
 
 	if (!state->fit_for_inline)
-		return;
+		return 0;
 
-	state->fit_for_inline = (loop_flag_is_zero(env) &&
+	flag_is_zero = loop_flag_is_zero(env);
+	if (flag_is_zero < 0)
+		return flag_is_zero;
+	state->fit_for_inline = (flag_is_zero &&
 				 state->callback_subprogno == subprogno);
+	return 0;
 }
 
 /* Returns whether or not the given map can potentially elide
@@ -10943,7 +10955,9 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 		err = check_bpf_snprintf_call(env, regs);
 		break;
 	case BPF_FUNC_loop:
-		update_loop_inline_state(env, meta.subprogno);
+		err = update_loop_inline_state(env, meta.subprogno);
+		if (err)
+			return err;
 		/* Verifier relies on R1 value to determine if bpf_loop() iteration
 		 * is finished, thus mark it precise.
 		 */

-- 
2.55.0

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

* [PATCH bpf 10/10] bpf: use mark_arg_precision() in check_mem_size_reg()
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
                   ` (8 preceding siblings ...)
  2026-09-05  0:06 ` [PATCH bpf 09/10] bpf: propagate mark_chain_precision() errors out of loop_flag_is_zero() Eduard Zingerman
@ 2026-09-05  0:06 ` Eduard Zingerman
  2026-09-05  0:51   ` bot+bpf-ci
  2026-09-05  1:20 ` [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls patchwork-bot+netdevbpf
  10 siblings, 1 reply; 19+ messages in thread
From: Eduard Zingerman @ 2026-09-05  0:06 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor

Use newly added mark_arg_precision() helper in check_mem_size_reg().

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 kernel/bpf/verifier.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index dc1fef1ef1ef..fc57275f15b6 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7153,14 +7153,8 @@ static int check_mem_size_reg(struct bpf_verifier_env *env,
 	if (err && failure)
 		*failure = BPF_MEM_SIZE_FAIL_MEMORY;
 
-	if (!err) {
-		int regno = reg_from_argno(size_argno);
-
-		if (regno >= 0)
-			err = mark_chain_precision(env, regno);
-		else
-			err = mark_stack_arg_precision(env, arg_idx_from_argno(size_argno));
-	}
+	if (!err)
+		err = mark_arg_precision(env, size_argno);
 
 	return err;
 

-- 
2.55.0

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

* Re: [PATCH bpf 07/10] bpf: mark a NULL BTF_ID argument of a global subprogram precise
  2026-09-05  0:05 ` [PATCH bpf 07/10] bpf: mark a NULL BTF_ID argument of a global subprogram precise Eduard Zingerman
@ 2026-09-05  0:19   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-09-05  0:19 UTC (permalink / raw)
  To: Eduard Zingerman; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Missing precision marking for NULL register in `check_map_kptr_access` bypasses kptr type checks, enabling arbitrary kernel memory read/write.
--

commit 86bb17dfcff95ef6eeda4b1333ab93abe99ab7bb
Author: Eduard Zingerman <eddyz87@gmail.com>

bpf: mark a NULL BTF_ID argument of a global subprogram precise

btf_check_func_arg_match() accepts a NULL register for an
ARG_PTR_TO_BTF_ID argument tagged __arg_nullable and skips
check_reg_type() and check_func_arg_reg_off() without marking the
register precise. Hence a checkpoint created on such a path would
prune against arbitrary scalar value.

> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 2b3d080978062..3c3575215899b 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -9767,8 +9767,12 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
>  			struct bpf_call_arg_meta meta;
>  			int err;
>  
> -			if (bpf_register_is_null(reg) && type_may_be_null(arg->arg_type))
> +			if (bpf_register_is_null(reg) && type_may_be_null(arg->arg_type)) {
> +				err = mark_arg_precision(env, argno);
> +				if (err)
> +					return err;
>  				continue;
> +			}
>  
>  			memset(&meta, 0, sizeof(meta)); /* leave func_id as zero */

[Severity: Critical]
This isn't a bug introduced by this patch, but does the same missing
precision issue exist in check_map_kptr_access() for BPF_STX operations?

Looking at check_map_kptr_access() when handling BPF_STX:

	} else if (class == BPF_STX) {
		val_reg = reg_state(env, value_regno);
		if (!bpf_register_is_null(val_reg) &&
		    map_kptr_match_type(env, kptr_field, val_reg, value_regno))
			return -EACCES;
	}

If a BPF program branch sets the register to 0, bpf_register_is_null()
returns true, and the type check is skipped without calling
mark_chain_precision().

Could a subsequent branch set the same register to an arbitrary non-zero
scalar and get incorrectly pruned by regsafe() because it compares against
the imprecise 0?

This sequence appears to allow storing an arbitrary scalar as a forged
pointer into a map. This could then lead to arbitrary memory read/write or
local privilege escalation when the kernel later drops or uses the kptr.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260904-register-is-null-precise-fixes-v1-0-0f5a360ff15d@gmail.com?part=7

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

* Re: [PATCH bpf 01/10] bpf: mark a NULL call argument precise
  2026-09-05  0:05 ` [PATCH bpf 01/10] bpf: mark a NULL call argument precise Eduard Zingerman
@ 2026-09-05  0:21   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-09-05  0:21 UTC (permalink / raw)
  To: Eduard Zingerman; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [Critical] This problem wasn't introduced by this patch, but the patch and the series fail to fix it while fixing identical vulnerabilities elsewhere. Missing precision tracking for nullable arguments was fixed in `check_func_arg()`, `check_helper_call()`, `check_kfunc_args()`, and `btf_check_func_arg_match()`. However, the exact same vulnerability remains in `check_map_kptr_access()`. When storing a NULL value into a kptr map field via `BPF_STX`, `check_map_kptr_access()` checks `bpf_register_is_null(val_reg)` to bypass pointer type validation. Because it skips validation on a NULL scalar without calling `mark_chain_precision()`, a checkpoint created with a NULL scalar in `val_reg` will incorrectly prune a subsequent path where `val_reg` holds an arbitrary, unconstrained scalar value. At runtime, this pruned path will execute and write an invalid scalar into the kptr field. When the map is later freed, the kernel will attempt to drop the kptr by treating the invalid scalar as a valid pointer, resulting in arbitrary kernel memory corruption.
--

commit a287fdd95b87b267c8cbd45bc11d4088d9532eb9
Author: Eduard Zingerman <eddyz87@gmail.com>

bpf: mark a NULL call argument precise

This commit fixes verifier pruning logic by marking NULL call arguments precise
in check_func_arg() and check_helper_call(). This prevents the verifier from
incorrectly pruning paths with unconstrained scalars against checkpoints with
NULL scalars.

> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 9c6ad157a61ec..ca362a7ea58c3 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -8752,11 +8752,15 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
>  			return err;
>  	}
>  
> -	if (bpf_register_is_null(reg) && type_may_be_null(arg_type))
> +	if (bpf_register_is_null(reg) && type_may_be_null(arg_type)) {
>  		/* A NULL register has a SCALAR_VALUE type, so skip
>  		 * type checking.
>  		 */
> +		err = mark_chain_precision(env, regno);
> +		if (err)
> +			return err;
>  		goto skip_type_check;
> +	}

[Severity: Critical]
This isn't a bug introduced by this patch, but the series appears to miss
an identical vulnerability in check_map_kptr_access().

When storing a NULL value into a kptr map field via BPF_STX,
check_map_kptr_access() checks bpf_register_is_null(val_reg) to bypass
pointer type validation:

kernel/bpf/verifier.c:check_map_kptr_access()
    } else if (class == BPF_STX) {
        val_reg = reg_state(env, value_regno);
        if (!bpf_register_is_null(val_reg) &&
            map_kptr_match_type(env, kptr_field, val_reg, value_regno))
            return -EACCES;
    }

Because it skips validation on a NULL scalar without calling
mark_chain_precision(), a checkpoint created with a NULL scalar in val_reg
could incorrectly prune a subsequent path where val_reg holds an arbitrary,
unconstrained scalar value.

At runtime, this pruned path could execute and write an invalid scalar into
the kptr field. When the map is later freed, the kernel would attempt to drop
the kptr by treating the invalid scalar as a valid pointer.

Could this lead to arbitrary kernel memory corruption? Should
mark_chain_precision() be called on value_regno when
bpf_register_is_null(val_reg) is true here as well?

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260904-register-is-null-precise-fixes-v1-0-0f5a360ff15d@gmail.com?part=1

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

* Re: [PATCH bpf 03/10] bpf: mark a NULL memory argument of a call precise
  2026-09-05  0:05 ` [PATCH bpf 03/10] bpf: mark a NULL memory argument of a call precise Eduard Zingerman
@ 2026-09-05  0:23   ` sashiko-bot
  2026-09-05  0:51   ` bot+bpf-ci
  1 sibling, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-09-05  0:23 UTC (permalink / raw)
  To: Eduard Zingerman; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Uninitialized variable `known_memory` is read on the error path in `check_kfunc_args` when handling NULL memory arguments.
--

commit 00db4f1dea6ce217e9633f69c742a410441956c2
Author: Eduard Zingerman <eddyz87@gmail.com>

bpf: mark a NULL memory argument of a call precise

This commit ensures that a NULL memory argument is correctly marked precise 
to prevent pruning against arbitrary scalar values. It also introduces a new
mark_arg_precision() helper to handle arguments that reside on the stack.

> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index ca362a7ea58c3..b758f28227540 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c

[ ... ]

> @@ -7168,7 +7177,7 @@ static int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg
>  	int size, err = 0;
>  
>  	if (bpf_register_is_null(reg))
> -		return 0;
> +		return mark_arg_precision(env, argno);

[Severity: Medium]
Does this early return path leave the `known_memory` pointer uninitialized 
if `mark_arg_precision()` fails?

Looking at its caller in `check_kfunc_args()`, `known_memory` is declared
without initialization:

kernel/bpf/verifier.c:check_kfunc_args() {
	...
	bool known_memory;
	...
	ret = check_mem_reg(env, reg, argno, type_size, BPF_READ | BPF_WRITE,
			    meta, &known_memory);
	if (ret < 0) {
		...
		if (known_memory)
			verbose(env, "...");
		else
			verbose(env, "...");
		return ret;
	}
	...
}

If `mark_arg_precision()` returns a negative error code (like `-EFAULT` from 
backtracking depth limits), `check_mem_reg()` will propagate it immediately 
before reaching the `if (known_memory) *known_memory = true;` block. 

Could this cause `check_kfunc_args()` to evaluate an uninitialized boolean 
variable when deciding which diagnostic message to print on the error path?

>  	if (known_memory)
>  		*known_memory = true;
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260904-register-is-null-precise-fixes-v1-0-0f5a360ff15d@gmail.com?part=3

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

* Re: [PATCH bpf 10/10] bpf: use mark_arg_precision() in check_mem_size_reg()
  2026-09-05  0:06 ` [PATCH bpf 10/10] bpf: use mark_arg_precision() in check_mem_size_reg() Eduard Zingerman
@ 2026-09-05  0:51   ` bot+bpf-ci
  0 siblings, 0 replies; 19+ messages in thread
From: bot+bpf-ci @ 2026-09-05  0:51 UTC (permalink / raw)
  To: eddyz87, bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor,
	ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, mason,
	ihor.solodrai

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

> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index e8af1d3dbdeb..1c3039f3fc32 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -7160,14 +7160,8 @@ static int check_mem_size_reg(struct bpf_verifier_env *env,
>  	if (err && failure)
>  		*failure = BPF_MEM_SIZE_FAIL_MEMORY;
>
> -	if (!err) {
> -		int regno = reg_from_argno(size_argno);
> -
> -		if (regno >= 0)
> -			err = mark_chain_precision(env, regno);
> -		else
> -			err = mark_stack_arg_precision(env, arg_idx_from_argno(size_argno));
> -	}
> +	if (!err)
> +		err = mark_arg_precision(env, size_argno);
>
>  	return err;

This isn't a bug, but since mark_arg_precision() now exists, could
process_const_arg() and process_const_alloc_mem_size() use it as well, so
the reg-vs-stack dispatch lives in one place? Both functions still
open-code the identical four-line pattern that was just replaced here.


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

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

* Re: [PATCH bpf 04/10] selftests/bpf: precision of a NULL global subprogram memory argument
  2026-09-05  0:05 ` [PATCH bpf 04/10] selftests/bpf: precision of a NULL global subprogram memory argument Eduard Zingerman
@ 2026-09-05  0:51   ` bot+bpf-ci
  0 siblings, 0 replies; 19+ messages in thread
From: bot+bpf-ci @ 2026-09-05  0:51 UTC (permalink / raw)
  To: eddyz87, bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor,
	ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, mason,
	ihor.solodrai

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

> diff --git a/tools/testing/selftests/bpf/progs/verifier_precision.c b/tools/testing/selftests/bpf/progs/verifier_precision.c
> index 3e290b07f672..fb7dfa1246ef 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_precision.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_precision.c
> @@ -676,4 +676,36 @@ __naked int null_mem_arg_zero_size(void)
>  		: __clobber_all);
>  }
>
> +__weak int subprog_mem_arg(int *p)
> +{
> +	if (p)
> +		return *p;
> +	return 0;
> +}
> +
> +/*
> + * Verification takes two paths: with r1 being scalar zero on path (1)
> + * and with r1 being some other scalar on path (2).
> + * Check that the verifier does not use checkpoints created
> + * on path (1) to prune path (2).
> + */

This isn't a bug, but this five-line comment above null_mem_arg_global_subprog
appears to be a verbatim copy of the comment above null_mem_arg_zero_size
earlier in the same file. Since the case just above already spells out the
two-path/pruning rationale in the same words, would a one-line back-reference
read better here, similar to how later patches in this series handle it?

> +SEC("?raw_tp")
> +__flag(BPF_F_TEST_STATE_FREQ)
> +__failure __msg("R1 type=scalar expected=fp")
> +__naked int null_mem_arg_global_subprog(void)
> +{
> +	asm volatile (
> +		"call %[bpf_get_prandom_u32];"
> +		"r1 = 42;"
> +		"if r0 > 42 goto 1f;"
> +		"r1 = 0;"
> +	"1:"
> +		"call subprog_mem_arg;"
> +		"r0 = 0;"
> +		"exit;"
> +		:
> +		: __imm(bpf_get_prandom_u32)
> +		: __clobber_all);
> +}


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

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

* Re: [PATCH bpf 03/10] bpf: mark a NULL memory argument of a call precise
  2026-09-05  0:05 ` [PATCH bpf 03/10] bpf: mark a NULL memory argument of a call precise Eduard Zingerman
  2026-09-05  0:23   ` sashiko-bot
@ 2026-09-05  0:51   ` bot+bpf-ci
  1 sibling, 0 replies; 19+ messages in thread
From: bot+bpf-ci @ 2026-09-05  0:51 UTC (permalink / raw)
  To: eddyz87, bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor,
	ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, mason,
	ihor.solodrai

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

> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index b107f551a62d..7926e131b1cb 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -4246,6 +4246,15 @@ static int mark_stack_arg_precision(struct bpf_verifier_env *env, int arg_idx)
>  	return mark_chain_precision_batch(env, env->cur_state);
>  }
>
> +static int mark_arg_precision(struct bpf_verifier_env *env, argno_t argno)
> +{
> +	int regno = reg_from_argno(argno);
> +
> +	if (regno >= 0)
> +		return mark_chain_precision(env, regno);
> +	return mark_stack_arg_precision(env, arg_idx_from_argno(argno));
> +}
> +

This isn't a bug, but since ee91facbfbf9 converts check_mem_size_reg()
to mark_arg_precision(), would it make sense to convert process_const_arg()
and process_const_alloc_mem_size() in the same cleanup?

Both still carry the open-coded pattern (if (regno >= 0)
mark_chain_precision(env, regno) else mark_stack_arg_precision(env,
arg_idx_from_argno(argno))), and both already compute regno =
reg_from_argno(argno) solely for that block.

>  static int check_outgoing_stack_args(struct bpf_verifier_env *env, struct bpf_func_state *caller,
>  				     int nargs, const char *callee_name, const struct btf *btf,
>  				     const struct btf_param *args)

[ ... ]

> @@ -7175,7 +7184,7 @@ static int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg
>  	int size, err = 0;
>
>  	if (bpf_register_is_null(reg))
> -		return 0;
> +		return mark_arg_precision(env, argno);
>  	if (known_memory)
>  		*known_memory = true;


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

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

* Re: [PATCH bpf 05/10] bpf: mark a NULL kfunc argument precise
  2026-09-05  0:05 ` [PATCH bpf 05/10] bpf: mark a NULL kfunc argument precise Eduard Zingerman
@ 2026-09-05  0:51   ` bot+bpf-ci
  0 siblings, 0 replies; 19+ messages in thread
From: bot+bpf-ci @ 2026-09-05  0:51 UTC (permalink / raw)
  To: eddyz87, bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, memxor,
	ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, mason,
	ihor.solodrai

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

> check_kfunc_arg() allows bpf_register_is_null() for nullable arguments
> w/o marking the underlying scalar register precise. Hence a checkpoint
> created on such a path would prune against arbitrary scalar value.
> Fixes: 3bda08b63670 ("bpf: Allow NULL buffers in bpf_dynptr_slice(_rw)")
> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>

Should the Fixes: tag point to commit 1690dcf27c73 instead?

The specific code path being fixed (the if statement with
bpf_register_is_null() and type_may_be_null() that continues without
marking precision) was introduced in commit 1690dcf27c73 ("bpf: Classify
scalar kfunc arguments from BTF"), not in 3bda08b63670. While commit
3bda08b63670 introduced nullable kfunc arguments, the precision marking
bug appears to have been introduced later during the refactoring in
1690dcf27c73.


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

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

* Re: [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls
  2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
                   ` (9 preceding siblings ...)
  2026-09-05  0:06 ` [PATCH bpf 10/10] bpf: use mark_arg_precision() in check_mem_size_reg() Eduard Zingerman
@ 2026-09-05  1:20 ` patchwork-bot+netdevbpf
  10 siblings, 0 replies; 19+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-05  1:20 UTC (permalink / raw)
  To: Eduard Zingerman
  Cc: bpf, ast, andrii, daniel, martin.lau, kernel-team, yonghong.song,
	memxor

Hello:

This series was applied to bpf/bpf.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Fri,  4 Sep 2026 17:05:51 -0700 you wrote:
> Fix [1] uncovered a host of locations where the call to
> bpf_register_is_null() is not followed by a call to
> bpf_mark_chain_precision().
> 
> check_map_kptr_access() is omitted as it is handled [2]
> by another series.
> 
> [...]

Here is the summary with links:
  - [bpf,01/10] bpf: mark a NULL call argument precise
    https://git.kernel.org/bpf/bpf/c/1a3a10b030c9
  - [bpf,02/10] selftests/bpf: precision of a NULL helper argument
    https://git.kernel.org/bpf/bpf/c/593c8eb0fb91
  - [bpf,03/10] bpf: mark a NULL memory argument of a call precise
    https://git.kernel.org/bpf/bpf/c/f1e418129f2e
  - [bpf,04/10] selftests/bpf: precision of a NULL global subprogram memory argument
    https://git.kernel.org/bpf/bpf/c/100f4cc0d59b
  - [bpf,05/10] bpf: mark a NULL kfunc argument precise
    https://git.kernel.org/bpf/bpf/c/506ada89629e
  - [bpf,06/10] selftests/bpf: precision of a NULL kfunc argument
    https://git.kernel.org/bpf/bpf/c/562d266d3fae
  - [bpf,07/10] bpf: mark a NULL BTF_ID argument of a global subprogram precise
    https://git.kernel.org/bpf/bpf/c/e726fc6b9afe
  - [bpf,08/10] selftests/bpf: precision of a NULL global subprogram BTF_ID argument
    https://git.kernel.org/bpf/bpf/c/91957791663f
  - [bpf,09/10] bpf: propagate mark_chain_precision() errors out of loop_flag_is_zero()
    https://git.kernel.org/bpf/bpf/c/1d7f8f191c06
  - [bpf,10/10] bpf: use mark_arg_precision() in check_mem_size_reg()
    https://git.kernel.org/bpf/bpf/c/cf2475616b11

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2026-09-05  1:21 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-05  0:05 [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls Eduard Zingerman
2026-09-05  0:05 ` [PATCH bpf 01/10] bpf: mark a NULL call argument precise Eduard Zingerman
2026-09-05  0:21   ` sashiko-bot
2026-09-05  0:05 ` [PATCH bpf 02/10] selftests/bpf: precision of a NULL helper argument Eduard Zingerman
2026-09-05  0:05 ` [PATCH bpf 03/10] bpf: mark a NULL memory argument of a call precise Eduard Zingerman
2026-09-05  0:23   ` sashiko-bot
2026-09-05  0:51   ` bot+bpf-ci
2026-09-05  0:05 ` [PATCH bpf 04/10] selftests/bpf: precision of a NULL global subprogram memory argument Eduard Zingerman
2026-09-05  0:51   ` bot+bpf-ci
2026-09-05  0:05 ` [PATCH bpf 05/10] bpf: mark a NULL kfunc argument precise Eduard Zingerman
2026-09-05  0:51   ` bot+bpf-ci
2026-09-05  0:05 ` [PATCH bpf 06/10] selftests/bpf: precision of a NULL kfunc argument Eduard Zingerman
2026-09-05  0:05 ` [PATCH bpf 07/10] bpf: mark a NULL BTF_ID argument of a global subprogram precise Eduard Zingerman
2026-09-05  0:19   ` sashiko-bot
2026-09-05  0:05 ` [PATCH bpf 08/10] selftests/bpf: precision of a NULL global subprogram BTF_ID argument Eduard Zingerman
2026-09-05  0:06 ` [PATCH bpf 09/10] bpf: propagate mark_chain_precision() errors out of loop_flag_is_zero() Eduard Zingerman
2026-09-05  0:06 ` [PATCH bpf 10/10] bpf: use mark_arg_precision() in check_mem_size_reg() Eduard Zingerman
2026-09-05  0:51   ` bot+bpf-ci
2026-09-05  1:20 ` [PATCH bpf 00/10] bpf: add missing precision propagation after bpf_register_is_null calls patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox