]> www.infradead.org Git - users/hch/misc.git/commitdiff
bpf: Add selftest to check the verifier's abstract multiplication
authorNandakumar Edamana <nandakumar@nandakumar.co.in>
Tue, 26 Aug 2025 03:45:24 +0000 (09:15 +0530)
committerAndrii Nakryiko <andrii@kernel.org>
Wed, 27 Aug 2025 22:00:31 +0000 (15:00 -0700)
Add new selftest to test the abstract multiplication technique(s) used
by the verifier, following the recent improvement in tnum
multiplication (tnum_mul). One of the newly added programs,
verifier_mul/mul_precise, results in a false positive with the old
tnum_mul, while the program passes with the latest one.

Signed-off-by: Nandakumar Edamana <nandakumar@nandakumar.co.in>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Harishankar Vishwanathan <harishankar.vishwanathan@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20250826034524.2159515-2-nandakumar@nandakumar.co.in
tools/testing/selftests/bpf/prog_tests/verifier.c
tools/testing/selftests/bpf/progs/verifier_mul.c [new file with mode: 0644]

index 77ec95d4ffaae9d0df0b7317870b6e42942b71be..e35c216dbaf21cf05a88475a247ef91f60d424ed 100644 (file)
@@ -59,6 +59,7 @@
 #include "verifier_meta_access.skel.h"
 #include "verifier_movsx.skel.h"
 #include "verifier_mtu.skel.h"
+#include "verifier_mul.skel.h"
 #include "verifier_netfilter_ctx.skel.h"
 #include "verifier_netfilter_retcode.skel.h"
 #include "verifier_bpf_fastcall.skel.h"
@@ -194,6 +195,7 @@ void test_verifier_may_goto_1(void)           { RUN(verifier_may_goto_1); }
 void test_verifier_may_goto_2(void)           { RUN(verifier_may_goto_2); }
 void test_verifier_meta_access(void)          { RUN(verifier_meta_access); }
 void test_verifier_movsx(void)                 { RUN(verifier_movsx); }
+void test_verifier_mul(void)                  { RUN(verifier_mul); }
 void test_verifier_netfilter_ctx(void)        { RUN(verifier_netfilter_ctx); }
 void test_verifier_netfilter_retcode(void)    { RUN(verifier_netfilter_retcode); }
 void test_verifier_bpf_fastcall(void)         { RUN(verifier_bpf_fastcall); }
diff --git a/tools/testing/selftests/bpf/progs/verifier_mul.c b/tools/testing/selftests/bpf/progs/verifier_mul.c
new file mode 100644 (file)
index 0000000..7145fe3
--- /dev/null
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Nandakumar Edamana */
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include "bpf_misc.h"
+
+/* Intended to test the abstract multiplication technique(s) used by
+ * the verifier. Using assembly to avoid compiler optimizations.
+ */
+SEC("fentry/bpf_fentry_test1")
+void BPF_PROG(mul_precise, int x)
+{
+       /* First, force the verifier to be uncertain about the value:
+        *     unsigned int a = (bpf_get_prandom_u32() & 0x2) | 0x1;
+        *
+        * Assuming the verifier is using tnum, a must be tnum{.v=0x1, .m=0x2}.
+        * Then a * 0x3 would be m0m1 (m for uncertain). Added imprecision
+        * would cause the following to fail, because the required return value
+        * is 0:
+        *     return (a * 0x3) & 0x4);
+        */
+       asm volatile ("\
+       call %[bpf_get_prandom_u32];\
+       r0 &= 0x2;\
+       r0 |= 0x1;\
+       r0 *= 0x3;\
+       r0 &= 0x4;\
+       if r0 != 0 goto l0_%=;\
+       r0 = 0;\
+       goto l1_%=;\
+l0_%=:\
+       r0 = 1;\
+l1_%=:\
+"      :
+       : __imm(bpf_get_prandom_u32)
+       : __clobber_all);
+}