summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduard Zingerman <eddyz87@gmail.com>2026-09-04 01:33:25 -0700
committerKumar Kartikeya Dwivedi <memxor@gmail.com>2026-09-04 12:58:05 +0200
commit6b31560c6bc1a8a7a70792c7b3ca4c1ea322063b (patch)
treeaf5c5d378e2ad3bc187ab0556cbdd51985d43450
parent6aed0134d3cda6382385a734ae0158eb7df6b142 (diff)
downloadlinux-6b31560c6bc1a8a7a70792c7b3ca4c1ea322063b.tar.gz
linux-6b31560c6bc1a8a7a70792c7b3ca4c1ea322063b.zip
selftests/bpf: No non-NULL inference from an imprecise zero register
Check that a register-form NULL check does not lift PTR_MAYBE_NULL on a path where the compared register is non-zero. W/o the previous patch the program is accepted. Reported-by: Nicholas Carlini <npc@anthropic.com> Suggested-by: Nicholas Carlini <npc@anthropic.com> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/bpf/20260904083325.2083493-8-eddyz87@gmail.com Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_jeq_infer_not_null.c34
1 files changed, 34 insertions, 0 deletions
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 410acbf658c7..3c789c565b18 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
@@ -418,6 +418,40 @@ __naked void jmp32_ptr_vs_zero_jne(void)
: __clobber_all);
}
+/*
+ * The below program is explored in two paths: r6 == 0 and r6 == 1.
+ * On the first path comparison "if r0 == r6 goto 2f" should mark r6 as precise,
+ * otherwise unsafe path with r6 == 1 would be incorrectly pruned.
+ */
+SEC("socket")
+__failure
+__flag(BPF_F_TEST_STATE_FREQ)
+__msg("error: invalid dereference of R0 (a nullable map value pointer)")
+__naked void imprecise_zero_does_not_infer_map_value_non_null(void)
+{
+ asm volatile (" \
+ call %[bpf_get_prandom_u32]; \
+ /* r6 is 0 on the path explored first, 1 on the other */\
+ r6 = 1; \
+ if r0 == 0 goto 1f; \
+ r6 = 0; \
+ /* r0 = bpf_map_lookup_elem(map_hash, &0); */ \
+1: *(u64 *)(r10 - 8) = 0; \
+ r1 = %[map_hash] ll; \
+ r2 = r10; \
+ r2 += -8; \
+ call %[bpf_map_lookup_elem]; \
+ if r0 == r6 goto 2f; \
+ r0 = *(u8 *)(r0 + 0); \
+2: r0 = 0; \
+ exit; \
+" :
+ : __imm(bpf_get_prandom_u32),
+ __imm(bpf_map_lookup_elem),
+ __imm_addr(map_hash)
+ : __clobber_all);
+}
+
void kfunc_root(void)
{
bpf_rdonly_cast(0, 0);