summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/bpf/progs/verifier_loops1.c
blob: 71735dbf33d4f868e32197fe5e6e051da9fa87da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
// SPDX-License-Identifier: GPL-2.0
/* Converted from tools/testing/selftests/bpf/verifier/loops1.c */

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include "bpf_misc.h"

SEC("xdp")
__description("bounded loop, count to 4")
__success __retval(4)
__naked void bounded_loop_count_to_4(void)
{
	asm volatile ("					\
	r0 = 0;						\
l0_%=:	r0 += 1;					\
	if r0 < 4 goto l0_%=;				\
	exit;						\
"	::: __clobber_all);
}

SEC("tracepoint")
__description("bounded loop, count to 20")
__success
__naked void bounded_loop_count_to_20(void)
{
	asm volatile ("					\
	r0 = 0;						\
l0_%=:	r0 += 3;					\
	if r0 < 20 goto l0_%=;				\
	exit;						\
"	::: __clobber_all);
}

SEC("tracepoint")
__description("bounded loop, count from positive unknown to 4")
__success
__naked void from_positive_unknown_to_4(void)
{
	asm volatile ("					\
	call %[bpf_get_prandom_u32];			\
	if r0 s< 0 goto l0_%=;				\
l1_%=:	r0 += 1;					\
	if r0 < 4 goto l1_%=;				\
l0_%=:	exit;						\
"	:
	: __imm(bpf_get_prandom_u32)
	: __clobber_all);
}

SEC("tracepoint")
__description("bounded loop, count from totally unknown to 4")
__success
__naked void from_totally_unknown_to_4(void)
{
	asm volatile ("					\
	call %[bpf_get_prandom_u32];			\
l0_%=:	r0 += 1;					\
	if r0 < 4 goto l0_%=;				\
	exit;						\
"	:
	: __imm(bpf_get_prandom_u32)
	: __clobber_all);
}

SEC("tracepoint")
__description("bounded loop, count to 4 with equality")
__success
__naked void count_to_4_with_equality(void)
{
	asm volatile ("					\
	r0 = 0;						\
l0_%=:	r0 += 1;					\
	if r0 != 4 goto l0_%=;				\
	exit;						\
"	::: __clobber_all);
}

SEC("socket")
__description("bounded loop, start in the middle")
__success
__failure_unpriv __msg_unpriv("back-edge")
__naked void loop_start_in_the_middle(void)
{
	asm volatile ("					\
	r0 = 0;						\
	goto l0_%=;					\
l1_%=:	r0 += 1;					\
l0_%=:	if r0 < 4 goto l1_%=;				\
	exit;						\
"	::: __clobber_all);
}

SEC("xdp")
__description("bounded loop containing a forward jump")
__success __retval(4)
__naked void loop_containing_a_forward_jump(void)
{
	asm volatile ("					\
	r0 = 0;						\
l1_%=:	r0 += 1;					\
	if r0 == r0 goto l0_%=;				\
l0_%=:	if r0 < 4 goto l1_%=;				\
	exit;						\
"	::: __clobber_all);
}

SEC("tracepoint")
__description("bounded loop that jumps out rather than in")
__success
__naked void jumps_out_rather_than_in(void)
{
	asm volatile ("					\
	r6 = 0;						\
l1_%=:	r6 += 1;					\
	if r6 > 10000 goto l0_%=;			\
	call %[bpf_get_prandom_u32];			\
	goto l1_%=;					\
l0_%=:	exit;						\
"	:
	: __imm(bpf_get_prandom_u32)
	: __clobber_all);
}

SEC("tracepoint")
__description("infinite loop after a conditional jump")
__failure __msg("program is too large")
__naked void loop_after_a_conditional_jump(void)
{
	asm volatile ("					\
	r0 = 5;						\
	if r0 < 4 goto l0_%=;				\
l1_%=:	r0 += 1;					\
	goto l1_%=;					\
l0_%=:	exit;						\
"	::: __clobber_all);
}

SEC("tracepoint")
__description("bounded recursion")
__failure
/* verifier limitation in detecting max stack depth */
__msg("the call stack of 8 frames is too deep !")
__naked void bounded_recursion(void)
{
	asm volatile ("					\
	r1 = 0;						\
	call bounded_recursion__1;			\
	exit;						\
"	::: __clobber_all);
}

static __naked __noinline __attribute__((used))
void bounded_recursion__1(void)
{
	asm volatile ("					\
	r1 += 1;					\
	r0 = r1;					\
	if r1 < 4 goto l0_%=;				\
	exit;						\
l0_%=:	call bounded_recursion__1;			\
	exit;						\
"	::: __clobber_all);
}

SEC("tracepoint")
__description("infinite loop in two jumps")
__failure __msg("loop detected")
__naked void infinite_loop_in_two_jumps(void)
{
	asm volatile ("					\
	r0 = 0;						\
l1_%=:	goto l0_%=;					\
l0_%=:	if r0 < 4 goto l1_%=;				\
	exit;						\
"	::: __clobber_all);
}

SEC("tracepoint")
__description("infinite loop: three-jump trick")
__failure __msg("loop detected")
__naked void infinite_loop_three_jump_trick(void)
{
	asm volatile ("					\
	r0 = 0;						\
l2_%=:	r0 += 1;					\
	r0 &= 1;					\
	if r0 < 2 goto l0_%=;				\
	exit;						\
l0_%=:	r0 += 1;					\
	r0 &= 1;					\
	if r0 < 2 goto l1_%=;				\
	exit;						\
l1_%=:	r0 += 1;					\
	r0 &= 1;					\
	if r0 < 2 goto l2_%=;				\
	exit;						\
"	::: __clobber_all);
}

SEC("xdp")
__description("not-taken loop with back jump to 1st insn")
__success __retval(123)
__naked void back_jump_to_1st_insn_1(void)
{
	asm volatile ("					\
l0_%=:	r0 = 123;					\
	if r0 == 4 goto l0_%=;				\
	exit;						\
"	::: __clobber_all);
}

SEC("xdp")
__description("taken loop with back jump to 1st insn")
__success __retval(55)
__naked void back_jump_to_1st_insn_2(void)
{
	asm volatile ("					\
	r1 = 10;					\
	r2 = 0;						\
	call back_jump_to_1st_insn_2__1;		\
	exit;						\
"	::: __clobber_all);
}

static __naked __noinline __attribute__((used))
void back_jump_to_1st_insn_2__1(void)
{
	asm volatile ("					\
l0_%=:	r2 += r1;					\
	r1 -= 1;					\
	if r1 != 0 goto l0_%=;				\
	r0 = r2;					\
	exit;						\
"	::: __clobber_all);
}

SEC("xdp")
__description("taken loop with back jump to 1st insn, 2")
__success __retval(55)
__naked void jump_to_1st_insn_2(void)
{
	asm volatile ("					\
	r1 = 10;					\
	r2 = 0;						\
	call jump_to_1st_insn_2__1;			\
	exit;						\
"	::: __clobber_all);
}

static __naked __noinline __attribute__((used))
void jump_to_1st_insn_2__1(void)
{
	asm volatile ("					\
l0_%=:	r2 += r1;					\
	r1 -= 1;					\
	if w1 != 0 goto l0_%=;				\
	r0 = r2;					\
	exit;						\
"	::: __clobber_all);
}

char _license[] SEC("license") = "GPL";