Files
linux/tools/testing/selftests/bpf/progs/verifier_mul.c
Nandakumar Edamana 2660b9d477 bpf: Add selftest to check the verifier's abstract multiplication
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
2025-08-27 15:00:31 -07:00

39 lines
1011 B
C

// 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);
}