summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduard Zingerman <eddyz87@gmail.com>2026-09-04 01:33:23 -0700
committerKumar Kartikeya Dwivedi <memxor@gmail.com>2026-09-04 12:58:04 +0200
commit836b2fe544a5e9b5ce116622cb36fba33838c6fd (patch)
tree95e38e4aaa0a6a78e373148b3d0af4aa2ab3d371
parente51179a4e09846f8fd0f26a05068520de2b301bf (diff)
downloadlinux-836b2fe544a5e9b5ce116622cb36fba33838c6fd.tar.gz
linux-836b2fe544a5e9b5ce116622cb36fba33838c6fd.zip
selftests/bpf: Check that JMP32 pointer vs zero jumps are not predicted
Add jmp32_ptr_vs_zero_jne: the fall-through of the 32-bit compare, which the verifier used to skip, contains an out of bounds map value access, hence w/o the previous patch the program is accepted. See previous patch for detailed description. 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-6-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.c27
1 files changed, 27 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 8657e4a0d601..410acbf658c7 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
@@ -391,6 +391,33 @@ __naked void bounded_offset_infers_map_value_non_null(void)
: __clobber_all);
}
+/*
+ * The low 32 bits of a map value pointer may be zero, hence a 32-bit
+ * compare with zero cannot be predicted from the pointer being non-NULL
+ * and both successors of such a jump have to be verified.
+ */
+SEC("socket")
+__failure __msg("invalid access to map value, value_size=4 off=32 size=4")
+__naked void jmp32_ptr_vs_zero_jne(void)
+{
+ asm volatile (" \
+ /* r0 = bpf_map_lookup_elem(map_hash, &key); */ \
+ *(u64 *)(r10 - 8) = 0; \
+ r1 = %[map_hash] ll; \
+ r2 = r10; \
+ r2 += -8; \
+ call %[bpf_map_lookup_elem]; \
+ if r0 == 0 goto 1f; \
+ if w0 != 0 goto 1f; \
+ r0 = *(u32 *)(r0 + 32); \
+1: r0 = 0; \
+ exit; \
+" :
+ : __imm(bpf_map_lookup_elem),
+ __imm_addr(map_hash)
+ : __clobber_all);
+}
+
void kfunc_root(void)
{
bpf_rdonly_cast(0, 0);