Skip to content

Commit f41d03a

Browse files
committed
selftests/bpf: tests with a loop state missing read/precision mark
The test case absent_mark_in_the_middle_state is equivalent of the following C program: 1: r8 = bpf_get_prandom_u32(); 2: r6 = -32; 3: bpf_iter_num_new(&fp[-8], 0, 10); 4: if (unlikely(bpf_get_prandom_u32())) 5: r6 = -31; 6: for (;;) { 7: if (!bpf_iter_num_next(&fp[-8])) 8: break; 9: if (unlikely(bpf_get_prandom_u32())) 10: *(u64 *)(fp + r6) = 7; 11: } 12: bpf_iter_num_destroy(&fp[-8]); 13: return 0; W/o a fix that instructs verifier to ignore branches count for loop entries verification proceeds as follows: - 1-4, state is {r6=-32,fp-8=active}; - 6, checkpoint A is created with {r6=-32,fp-8=active}; - 7, checkpoint B is created with {r6=-32,fp-8=active}, push state {r6=-32,fp-8=active} from 7 to 9; - 8,12,13, {r6=-32,fp-8=drained}, exit; - pop state with {r6=-32,fp-8=active} from 7 to 9; - 9, push state {r6=-32,fp-8=active} from 9 to 10; - 6, checkpoint C is created with {r6=-32,fp-8=active}; - 7, checkpoint A is hit, no precision propagated for r6 to C; - pop state {r6=-32,fp-8=active} from 9 to 10; - 10, state is {r6=-31,fp-8=active}, r6 is marked as read and precise, these marks are propagated to checkpoints A and B (but not C, as it is not the parent of current state; - 6, {r6=-31,fp-8=active} checkpoint C is hit, because r6 is not marked precise for this checkpoint; - the program is accepted, despite a possibility of unaligned u64 stack access at offset -31. The test case absent_mark_in_the_middle_state2 is similar except the following change: r8 = bpf_get_prandom_u32(); r6 = -32; bpf_iter_num_new(&fp[-8], 0, 10); if (unlikely(bpf_get_prandom_u32())) { r6 = -31; + jump_into_loop: + goto +0; + goto loop; + } + if (unlikely(bpf_get_prandom_u32())) + goto jump_into_loop; + loop: for (;;) { if (!bpf_iter_num_next(&fp[-8])) break; if (unlikely(bpf_get_prandom_u32())) *(u64 *)(fp + r6) = 7; } bpf_iter_num_destroy(&fp[-8]) return 0 The goal is to check that read/precision marks are propagated to checkpoint created at 'goto +0' that resides outside of the loop. Signed-off-by: Eduard Zingerman <[email protected]>
1 parent b2aaff1 commit f41d03a

File tree

1 file changed

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

1 file changed

+151
-0
lines changed

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

+151
Original file line numberDiff line numberDiff line change
@@ -1649,4 +1649,155 @@ int clean_live_states(const void *ctx)
16491649
return 0;
16501650
}
16511651

1652+
SEC("?raw_tp")
1653+
__flag(BPF_F_TEST_STATE_FREQ)
1654+
__failure __msg("misaligned stack access off 0+-31+0 size 8")
1655+
__naked int absent_mark_in_the_middle_state(void)
1656+
{
1657+
/* This is equivalent to C program below.
1658+
*
1659+
* r8 = bpf_get_prandom_u32();
1660+
* r6 = -32;
1661+
* bpf_iter_num_new(&fp[-8], 0, 10);
1662+
* if (unlikely(bpf_get_prandom_u32()))
1663+
* r6 = -31;
1664+
* while (bpf_iter_num_next(&fp[-8])) {
1665+
* if (unlikely(bpf_get_prandom_u32()))
1666+
* *(fp + r6) = 7;
1667+
* }
1668+
* bpf_iter_num_destroy(&fp[-8])
1669+
* return 0
1670+
*/
1671+
asm volatile (
1672+
"call %[bpf_get_prandom_u32];"
1673+
"r8 = r0;"
1674+
"r7 = 0;"
1675+
"r6 = -32;"
1676+
"r0 = 0;"
1677+
"*(u64 *)(r10 - 16) = r0;"
1678+
"r1 = r10;"
1679+
"r1 += -8;"
1680+
"r2 = 0;"
1681+
"r3 = 10;"
1682+
"call %[bpf_iter_num_new];"
1683+
"call %[bpf_get_prandom_u32];"
1684+
"if r0 == r8 goto change_r6_%=;"
1685+
"loop_%=:"
1686+
"call noop;"
1687+
"r1 = r10;"
1688+
"r1 += -8;"
1689+
"call %[bpf_iter_num_next];"
1690+
"if r0 == 0 goto loop_end_%=;"
1691+
"call %[bpf_get_prandom_u32];"
1692+
"if r0 == r8 goto use_r6_%=;"
1693+
"goto loop_%=;"
1694+
"loop_end_%=:"
1695+
"r1 = r10;"
1696+
"r1 += -8;"
1697+
"call %[bpf_iter_num_destroy];"
1698+
"r0 = 0;"
1699+
"exit;"
1700+
"use_r6_%=:"
1701+
"r0 = r10;"
1702+
"r0 += r6;"
1703+
"r1 = 7;"
1704+
"*(u64 *)(r0 + 0) = r1;"
1705+
"goto loop_%=;"
1706+
"change_r6_%=:"
1707+
"r6 = -31;"
1708+
"goto loop_%=;"
1709+
:
1710+
: __imm(bpf_iter_num_new),
1711+
__imm(bpf_iter_num_next),
1712+
__imm(bpf_iter_num_destroy),
1713+
__imm(bpf_get_prandom_u32)
1714+
: __clobber_all
1715+
);
1716+
}
1717+
1718+
__used __naked
1719+
static int noop(void)
1720+
{
1721+
asm volatile (
1722+
"r0 = 0;"
1723+
"exit;"
1724+
);
1725+
}
1726+
1727+
SEC("?raw_tp")
1728+
__flag(BPF_F_TEST_STATE_FREQ)
1729+
__failure __msg("misaligned stack access off 0+-31+0 size 8")
1730+
__naked int absent_mark_in_the_middle_state2(void)
1731+
{
1732+
/* This is equivalent to C program below.
1733+
*
1734+
* r8 = bpf_get_prandom_u32();
1735+
* r6 = -32;
1736+
* bpf_iter_num_new(&fp[-8], 0, 10);
1737+
* if (unlikely(bpf_get_prandom_u32())) {
1738+
* r6 = -31;
1739+
* jump_into_loop:
1740+
* goto +0;
1741+
* goto loop;
1742+
* }
1743+
* if (unlikely(bpf_get_prandom_u32()))
1744+
* goto jump_into_loop;
1745+
* loop:
1746+
* while (bpf_iter_num_next(&fp[-8])) {
1747+
* if (unlikely(bpf_get_prandom_u32()))
1748+
* *(fp + r6) = 7;
1749+
* }
1750+
* bpf_iter_num_destroy(&fp[-8])
1751+
* return 0
1752+
*/
1753+
asm volatile (
1754+
"call %[bpf_get_prandom_u32];"
1755+
"r8 = r0;"
1756+
"r7 = 0;"
1757+
"r6 = -32;"
1758+
"r0 = 0;"
1759+
"*(u64 *)(r10 - 16) = r0;"
1760+
"r1 = r10;"
1761+
"r1 += -8;"
1762+
"r2 = 0;"
1763+
"r3 = 10;"
1764+
"call %[bpf_iter_num_new];"
1765+
"call %[bpf_get_prandom_u32];"
1766+
"if r0 == r8 goto change_r6_%=;"
1767+
"call %[bpf_get_prandom_u32];"
1768+
"if r0 == r8 goto jump_into_loop_%=;"
1769+
"loop_%=:"
1770+
"r1 = r10;"
1771+
"r1 += -8;"
1772+
"call %[bpf_iter_num_next];"
1773+
"if r0 == 0 goto loop_end_%=;"
1774+
"call %[bpf_get_prandom_u32];"
1775+
"if r0 == r8 goto use_r6_%=;"
1776+
"goto loop_%=;"
1777+
"loop_end_%=:"
1778+
"r1 = r10;"
1779+
"r1 += -8;"
1780+
"call %[bpf_iter_num_destroy];"
1781+
"r0 = 0;"
1782+
"exit;"
1783+
"use_r6_%=:"
1784+
"r0 = r10;"
1785+
"r0 += r6;"
1786+
"r1 = 7;"
1787+
"*(u64 *)(r0 + 0) = r1;"
1788+
"goto loop_%=;"
1789+
"change_r6_%=:"
1790+
"r6 = -31;"
1791+
"jump_into_loop_%=: "
1792+
"goto +0;"
1793+
"goto loop_%=;"
1794+
:
1795+
: __imm(bpf_iter_num_new),
1796+
__imm(bpf_iter_num_next),
1797+
__imm(bpf_iter_num_destroy),
1798+
__imm(bpf_get_prandom_u32)
1799+
: __clobber_all
1800+
);
1801+
}
1802+
16521803
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)