[PATCH bpf-next 2/2] selftests/bpf: a demo for check_cond_jmp_op() non-null inference bug

Eduard Zingerman <[email protected]>
Newsgroups org.kernel.vger.bpf
Message-ID <20260821-bug-029-bad-non-null-inference-v1-2-45ddc0f7c308@gmail.com>
A comparison between PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED and
PTR_TO_MAP_VALUE_OR_NULL should not infer that map pointer is not null.
A bug in check_cond_jmp_op() made such inference possible.

Signed-off-by: Eduard Zingerman <[email protected]>
---
 .../bpf/progs/verifier_jeq_infer_not_null.c        | 44 ++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/verifier_jeq_infer_not_null.c b/tools/testing/selftests/bpf/progs/verifier_jeq_infer_not_null.c
index 3d1e8de4390c..085d1146896c 100644
--- a/tools/testing/selftests/bpf/progs/verifier_jeq_infer_not_null.c
+++ b/tools/testing/selftests/bpf/progs/verifier_jeq_infer_not_null.c
@@ -3,7 +3,9 @@
 
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
+#include <stdbool.h>
 #include "bpf_misc.h"
+#include "bpf_kfuncs.h"
 
 struct {
 	__uint(type, BPF_MAP_TYPE_XSKMAP);
@@ -264,4 +266,46 @@ __naked void jne_reg_reg_null_check(void)
         : __clobber_all);
 }
 
+/*
+ * A comparison between PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED and
+ * PTR_TO_MAP_VALUE_OR_NULL should not infer that map pointer is not null.
+ * A bug in check_cond_jmp_op() made such inference possible.
+ */
+SEC("raw_tp")
+__failure
+__msg("error: invalid dereference of R0 (xdp_sock_or_null)")
+__msg(">>> 10 | (61) r0 = *(u32 *)(r0 +0)")
+__naked void untrusted_mem_does_not_infer_map_value_non_null(void)
+{
+	asm volatile ("					\
+	/* r8 = bpf_rdonly_cast(0, 0); */		\
+	r2 = 0;						\
+	call %[bpf_rdonly_cast];			\
+	r6 = r0;					\
+	/* r0 = bpf_map_lookup_elem(map_hash, &key); */	\
+	*(u64 *)(r10 - 8) = 0;				\
+	r1 = %[map_xskmap] ll;				\
+	r2 = r10;					\
+	r2 += -8;					\
+	call %[bpf_map_lookup_elem];			\
+	/*						\
+	 * buggy verifier assumed that r6 can't be null	\
+	 * and marked r0 non-null as well.		\
+	 */						\
+	if r6 != r0 goto 1f;				\
+	r0 = *(u32 *)(r0 + 0);				\
+1:	r0 = 0;						\
+	exit;						\
+"	:
+	: __imm(bpf_rdonly_cast),
+	  __imm(bpf_map_lookup_elem),
+	  __imm_addr(map_xskmap)
+	: __clobber_all);
+}
+
+void kfunc_root(void)
+{
+	bpf_rdonly_cast(0, 0);
+}
+
 char _license[] SEC("license") = "GPL";

-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.