Skip to content

Commit f7fc7fb

Browse files
Eduard Zingermaneddyz87
authored andcommitted
selftests/bpf: test cases for bpf_loop SCC and state graph backedges
Test for state graph backedges accumulation for SCCs formed bt bpf_loop(). Equivalent to the following C program: int main(void) { 1: fp[-8] = bpf_get_prandom_u32(); 2: fp[-16] = -32; // used in a memory access below 3: bpf_loop(7, loop_cb4, fp, 0); 4: return 0; } int loop_cb4(int i, void *ctx) { 5: if (unlikely(ctx[-8] > bpf_get_prandom_u32())) 6: *(u64 *)(fp + ctx[-16]) = 42; // aligned access expected 7: if (unlikely(fp[-8] > bpf_get_prandom_u32())) 8: ctx[-16] = -31; // makes said access unaligned 9: return 0; } If state graph backedges are not accumulated properly at SCC formed by loop_cb4() call from bpf_loop(), the state {ctx[-16]=-32} injected at 9 on verification path 1,2,3,5,7,9,4 would be considered as complete and lack precision mark for ctx[-16]. Leading to early pruning of verification path 1,2,3,5,7,8,9 in state {ctx[-16]=-31}. Leading to an assumption that the above program is safe. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
1 parent 64ccd8d commit f7fc7fb

File tree

1 file changed

+75
-0
lines changed
  • tools/testing/selftests/bpf/progs

1 file changed

+75
-0
lines changed

tools/testing/selftests/bpf/progs/iters.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,4 +1926,79 @@ static int loop1_wrapper(void)
19261926
);
19271927
}
19281928

1929+
/*
1930+
* This is similar to a test case absent_mark_in_the_middle_state(),
1931+
* but adapted for use with bpf_loop().
1932+
*/
1933+
SEC("raw_tp")
1934+
__flag(BPF_F_TEST_STATE_FREQ)
1935+
__failure __msg("math between fp pointer and register with unbounded min value is not allowed")
1936+
__naked void absent_mark_in_the_middle_state4(void)
1937+
{
1938+
/*
1939+
* Equivalent to a C program below:
1940+
*
1941+
* int main(void) {
1942+
* fp[-8] = bpf_get_prandom_u32();
1943+
* fp[-16] = -32; // used in a memory access below
1944+
* bpf_loop(7, loop_cb4, fp, 0);
1945+
* return 0;
1946+
* }
1947+
*
1948+
* int loop_cb4(int i, void *ctx) {
1949+
* if (unlikely(ctx[-8] > bpf_get_prandom_u32()))
1950+
* *(u64 *)(fp + ctx[-16]) = 42; // aligned access expected
1951+
* if (unlikely(fp[-8] > bpf_get_prandom_u32()))
1952+
* ctx[-16] = -31; // makes said access unaligned
1953+
* return 0;
1954+
* }
1955+
*/
1956+
asm volatile (
1957+
"call %[bpf_get_prandom_u32];"
1958+
"r8 = r0;"
1959+
"*(u64 *)(r10 - 8) = r0;"
1960+
"*(u64 *)(r10 - 16) = -32;"
1961+
"r1 = 7;"
1962+
"r2 = loop_cb4 ll;"
1963+
"r3 = r10;"
1964+
"r4 = 0;"
1965+
"call %[bpf_loop];"
1966+
"r0 = 0;"
1967+
"exit;"
1968+
:
1969+
: __imm(bpf_loop),
1970+
__imm(bpf_get_prandom_u32)
1971+
: __clobber_all
1972+
);
1973+
}
1974+
1975+
__used __naked
1976+
static void loop_cb4(void)
1977+
{
1978+
asm volatile (
1979+
"r9 = r2;"
1980+
"r8 = *(u64 *)(r9 - 8);"
1981+
"r6 = *(u64 *)(r9 - 16);"
1982+
"call %[bpf_get_prandom_u32];"
1983+
"if r0 > r8 goto use_fp16_%=;"
1984+
"1:"
1985+
"call %[bpf_get_prandom_u32];"
1986+
"if r0 > r8 goto update_fp16_%=;"
1987+
"2:"
1988+
"r0 = 0;"
1989+
"exit;"
1990+
"use_fp16_%=:"
1991+
"r1 = r10;"
1992+
"r1 += r6;"
1993+
"*(u64 *)(r1 + 0) = 42;"
1994+
"goto 1b;"
1995+
"update_fp16_%=:"
1996+
"*(u64 *)(r9 - 16) = -31;"
1997+
"goto 2b;"
1998+
:
1999+
: __imm(bpf_get_prandom_u32)
2000+
: __clobber_all
2001+
);
2002+
}
2003+
19292004
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)