Skip to content

Commit 7960d02

Browse files
bjackmanAlexei Starovoitov
authored andcommitted
selftests/bpf: Some more atomic tests
Some new verifier tests that hit some important gaps in the parameter space for atomic ops. There are already exhaustive tests for the JIT part in lib/test_bpf.c, but these exercise the verifier too. Signed-off-by: Brendan Jackman <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 99aaebf commit 7960d02

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,41 @@
119119
},
120120
.result = ACCEPT,
121121
},
122+
{
123+
"Dest pointer in r0 - fail",
124+
.insns = {
125+
/* val = 0; */
126+
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
127+
/* r0 = &val */
128+
BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
129+
/* r0 = atomic_cmpxchg(&val, r0, 1); */
130+
BPF_MOV64_IMM(BPF_REG_1, 1),
131+
BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
132+
/* if (r0 != 0) exit(1); */
133+
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
134+
BPF_MOV64_IMM(BPF_REG_0, 1),
135+
BPF_EXIT_INSN(),
136+
/* exit(0); */
137+
BPF_MOV64_IMM(BPF_REG_0, 0),
138+
BPF_EXIT_INSN(),
139+
},
140+
.result = ACCEPT,
141+
},
142+
{
143+
"Dest pointer in r0 - succeed",
144+
.insns = {
145+
/* r0 = &val */
146+
BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
147+
/* val = r0; */
148+
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
149+
/* r0 = atomic_cmpxchg(&val, r0, 0); */
150+
BPF_MOV64_IMM(BPF_REG_1, 0),
151+
BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
152+
/* r1 = *r0 */
153+
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),
154+
/* exit(0); */
155+
BPF_MOV64_IMM(BPF_REG_0, 0),
156+
BPF_EXIT_INSN(),
157+
},
158+
.result = ACCEPT,
159+
},
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#define __ATOMIC_FETCH_OP_TEST(src_reg, dst_reg, operand1, op, operand2, expect) \
2+
{ \
3+
"atomic fetch " #op ", src=" #dst_reg " dst=" #dst_reg, \
4+
.insns = { \
5+
/* u64 val = operan1; */ \
6+
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, operand1), \
7+
/* u64 old = atomic_fetch_add(&val, operand2); */ \
8+
BPF_MOV64_REG(dst_reg, BPF_REG_10), \
9+
BPF_MOV64_IMM(src_reg, operand2), \
10+
BPF_ATOMIC_OP(BPF_DW, op, \
11+
dst_reg, src_reg, -8), \
12+
/* if (old != operand1) exit(1); */ \
13+
BPF_JMP_IMM(BPF_JEQ, src_reg, operand1, 2), \
14+
BPF_MOV64_IMM(BPF_REG_0, 1), \
15+
BPF_EXIT_INSN(), \
16+
/* if (val != result) exit (2); */ \
17+
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -8), \
18+
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, expect, 2), \
19+
BPF_MOV64_IMM(BPF_REG_0, 2), \
20+
BPF_EXIT_INSN(), \
21+
/* exit(0); */ \
22+
BPF_MOV64_IMM(BPF_REG_0, 0), \
23+
BPF_EXIT_INSN(), \
24+
}, \
25+
.result = ACCEPT, \
26+
}
27+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_2, 1, BPF_ADD | BPF_FETCH, 2, 3),
28+
__ATOMIC_FETCH_OP_TEST(BPF_REG_0, BPF_REG_1, 1, BPF_ADD | BPF_FETCH, 2, 3),
29+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_0, 1, BPF_ADD | BPF_FETCH, 2, 3),
30+
__ATOMIC_FETCH_OP_TEST(BPF_REG_2, BPF_REG_3, 1, BPF_ADD | BPF_FETCH, 2, 3),
31+
__ATOMIC_FETCH_OP_TEST(BPF_REG_4, BPF_REG_5, 1, BPF_ADD | BPF_FETCH, 2, 3),
32+
__ATOMIC_FETCH_OP_TEST(BPF_REG_9, BPF_REG_8, 1, BPF_ADD | BPF_FETCH, 2, 3),
33+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_2, 0x010, BPF_AND | BPF_FETCH, 0x011, 0x010),
34+
__ATOMIC_FETCH_OP_TEST(BPF_REG_0, BPF_REG_1, 0x010, BPF_AND | BPF_FETCH, 0x011, 0x010),
35+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_0, 0x010, BPF_AND | BPF_FETCH, 0x011, 0x010),
36+
__ATOMIC_FETCH_OP_TEST(BPF_REG_2, BPF_REG_3, 0x010, BPF_AND | BPF_FETCH, 0x011, 0x010),
37+
__ATOMIC_FETCH_OP_TEST(BPF_REG_4, BPF_REG_5, 0x010, BPF_AND | BPF_FETCH, 0x011, 0x010),
38+
__ATOMIC_FETCH_OP_TEST(BPF_REG_9, BPF_REG_8, 0x010, BPF_AND | BPF_FETCH, 0x011, 0x010),
39+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_2, 0x010, BPF_OR | BPF_FETCH, 0x011, 0x011),
40+
__ATOMIC_FETCH_OP_TEST(BPF_REG_0, BPF_REG_1, 0x010, BPF_OR | BPF_FETCH, 0x011, 0x011),
41+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_0, 0x010, BPF_OR | BPF_FETCH, 0x011, 0x011),
42+
__ATOMIC_FETCH_OP_TEST(BPF_REG_2, BPF_REG_3, 0x010, BPF_OR | BPF_FETCH, 0x011, 0x011),
43+
__ATOMIC_FETCH_OP_TEST(BPF_REG_4, BPF_REG_5, 0x010, BPF_OR | BPF_FETCH, 0x011, 0x011),
44+
__ATOMIC_FETCH_OP_TEST(BPF_REG_9, BPF_REG_8, 0x010, BPF_OR | BPF_FETCH, 0x011, 0x011),
45+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_2, 0x010, BPF_XOR | BPF_FETCH, 0x011, 0x001),
46+
__ATOMIC_FETCH_OP_TEST(BPF_REG_0, BPF_REG_1, 0x010, BPF_XOR | BPF_FETCH, 0x011, 0x001),
47+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_0, 0x010, BPF_XOR | BPF_FETCH, 0x011, 0x001),
48+
__ATOMIC_FETCH_OP_TEST(BPF_REG_2, BPF_REG_3, 0x010, BPF_XOR | BPF_FETCH, 0x011, 0x001),
49+
__ATOMIC_FETCH_OP_TEST(BPF_REG_4, BPF_REG_5, 0x010, BPF_XOR | BPF_FETCH, 0x011, 0x001),
50+
__ATOMIC_FETCH_OP_TEST(BPF_REG_9, BPF_REG_8, 0x010, BPF_XOR | BPF_FETCH, 0x011, 0x001),
51+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_2, 0x010, BPF_XCHG, 0x011, 0x011),
52+
__ATOMIC_FETCH_OP_TEST(BPF_REG_0, BPF_REG_1, 0x010, BPF_XCHG, 0x011, 0x011),
53+
__ATOMIC_FETCH_OP_TEST(BPF_REG_1, BPF_REG_0, 0x010, BPF_XCHG, 0x011, 0x011),
54+
__ATOMIC_FETCH_OP_TEST(BPF_REG_2, BPF_REG_3, 0x010, BPF_XCHG, 0x011, 0x011),
55+
__ATOMIC_FETCH_OP_TEST(BPF_REG_4, BPF_REG_5, 0x010, BPF_XCHG, 0x011, 0x011),
56+
__ATOMIC_FETCH_OP_TEST(BPF_REG_9, BPF_REG_8, 0x010, BPF_XCHG, 0x011, 0x011),
57+
#undef __ATOMIC_FETCH_OP_TEST
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#define __INVALID_ATOMIC_ACCESS_TEST(op) \
2+
{ \
3+
"atomic " #op " access through non-pointer ", \
4+
.insns = { \
5+
BPF_MOV64_IMM(BPF_REG_0, 1), \
6+
BPF_MOV64_IMM(BPF_REG_1, 0), \
7+
BPF_ATOMIC_OP(BPF_DW, op, BPF_REG_1, BPF_REG_0, -8), \
8+
BPF_MOV64_IMM(BPF_REG_0, 0), \
9+
BPF_EXIT_INSN(), \
10+
}, \
11+
.result = REJECT, \
12+
.errstr = "R1 invalid mem access 'inv'" \
13+
}
14+
__INVALID_ATOMIC_ACCESS_TEST(BPF_ADD),
15+
__INVALID_ATOMIC_ACCESS_TEST(BPF_ADD | BPF_FETCH),
16+
__INVALID_ATOMIC_ACCESS_TEST(BPF_ADD),
17+
__INVALID_ATOMIC_ACCESS_TEST(BPF_ADD | BPF_FETCH),
18+
__INVALID_ATOMIC_ACCESS_TEST(BPF_AND),
19+
__INVALID_ATOMIC_ACCESS_TEST(BPF_AND | BPF_FETCH),
20+
__INVALID_ATOMIC_ACCESS_TEST(BPF_OR),
21+
__INVALID_ATOMIC_ACCESS_TEST(BPF_OR | BPF_FETCH),
22+
__INVALID_ATOMIC_ACCESS_TEST(BPF_XOR),
23+
__INVALID_ATOMIC_ACCESS_TEST(BPF_XOR | BPF_FETCH),
24+
__INVALID_ATOMIC_ACCESS_TEST(BPF_XCHG),
25+
__INVALID_ATOMIC_ACCESS_TEST(BPF_CMPXCHG),

0 commit comments

Comments
 (0)