xref: /linux/tools/testing/selftests/bpf/progs/verifier_mul.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2025 Nandakumar Edamana */
3 #include <linux/bpf.h>
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
6 #include "bpf_misc.h"
7 
8 /* Intended to test the abstract multiplication technique(s) used by
9  * the verifier. Using assembly to avoid compiler optimizations.
10  */
11 SEC("fentry/bpf_fentry_test1")
12 void BPF_PROG(mul_precise, int x)
13 {
14 	/* First, force the verifier to be uncertain about the value:
15 	 *     unsigned int a = (bpf_get_prandom_u32() & 0x2) | 0x1;
16 	 *
17 	 * Assuming the verifier is using tnum, a must be tnum{.v=0x1, .m=0x2}.
18 	 * Then a * 0x3 would be m0m1 (m for uncertain). Added imprecision
19 	 * would cause the following to fail, because the required return value
20 	 * is 0:
21 	 *     return (a * 0x3) & 0x4);
22 	 */
23 	asm volatile ("\
24 	call %[bpf_get_prandom_u32];\
25 	r0 &= 0x2;\
26 	r0 |= 0x1;\
27 	r0 *= 0x3;\
28 	r0 &= 0x4;\
29 	if r0 != 0 goto l0_%=;\
30 	r0 = 0;\
31 	goto l1_%=;\
32 l0_%=:\
33 	r0 = 1;\
34 l1_%=:\
35 "	:
36 	: __imm(bpf_get_prandom_u32)
37 	: __clobber_all);
38 }
39