Commit | Line | Data |
---|---|---|
5a77a01f EZ |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Converted from tools/testing/selftests/bpf/verifier/raw_stack.c */ | |
3 | ||
4 | #include <linux/bpf.h> | |
5 | #include <bpf/bpf_helpers.h> | |
6 | #include "bpf_misc.h" | |
7 | ||
6b4a64ba | 8 | SEC("socket") |
5a77a01f | 9 | __description("raw_stack: no skb_load_bytes") |
6b4a64ba AM |
10 | __success |
11 | __failure_unpriv __msg_unpriv("invalid read from stack R6 off=-8 size=8") | |
5a77a01f EZ |
12 | __naked void stack_no_skb_load_bytes(void) |
13 | { | |
14 | asm volatile (" \ | |
15 | r2 = 4; \ | |
16 | r6 = r10; \ | |
17 | r6 += -8; \ | |
18 | r3 = r6; \ | |
19 | r4 = 8; \ | |
20 | /* Call to skb_load_bytes() omitted. */ \ | |
21 | r0 = *(u64*)(r6 + 0); \ | |
22 | exit; \ | |
23 | " ::: __clobber_all); | |
24 | } | |
25 | ||
26 | SEC("tc") | |
27 | __description("raw_stack: skb_load_bytes, negative len") | |
28 | __failure __msg("R4 min value is negative") | |
29 | __naked void skb_load_bytes_negative_len(void) | |
30 | { | |
31 | asm volatile (" \ | |
32 | r2 = 4; \ | |
33 | r6 = r10; \ | |
34 | r6 += -8; \ | |
35 | r3 = r6; \ | |
36 | r4 = -8; \ | |
37 | call %[bpf_skb_load_bytes]; \ | |
38 | r0 = *(u64*)(r6 + 0); \ | |
39 | exit; \ | |
40 | " : | |
41 | : __imm(bpf_skb_load_bytes) | |
42 | : __clobber_all); | |
43 | } | |
44 | ||
45 | SEC("tc") | |
46 | __description("raw_stack: skb_load_bytes, negative len 2") | |
47 | __failure __msg("R4 min value is negative") | |
48 | __naked void load_bytes_negative_len_2(void) | |
49 | { | |
50 | asm volatile (" \ | |
51 | r2 = 4; \ | |
52 | r6 = r10; \ | |
53 | r6 += -8; \ | |
54 | r3 = r6; \ | |
55 | r4 = %[__imm_0]; \ | |
56 | call %[bpf_skb_load_bytes]; \ | |
57 | r0 = *(u64*)(r6 + 0); \ | |
58 | exit; \ | |
59 | " : | |
60 | : __imm(bpf_skb_load_bytes), | |
61 | __imm_const(__imm_0, ~0) | |
62 | : __clobber_all); | |
63 | } | |
64 | ||
65 | SEC("tc") | |
66 | __description("raw_stack: skb_load_bytes, zero len") | |
8a021e7f | 67 | __failure __msg("R4 invalid zero-sized read: u64=[0,0]") |
5a77a01f EZ |
68 | __naked void skb_load_bytes_zero_len(void) |
69 | { | |
70 | asm volatile (" \ | |
71 | r2 = 4; \ | |
72 | r6 = r10; \ | |
73 | r6 += -8; \ | |
74 | r3 = r6; \ | |
75 | r4 = 0; \ | |
76 | call %[bpf_skb_load_bytes]; \ | |
77 | r0 = *(u64*)(r6 + 0); \ | |
78 | exit; \ | |
79 | " : | |
80 | : __imm(bpf_skb_load_bytes) | |
81 | : __clobber_all); | |
82 | } | |
83 | ||
84 | SEC("tc") | |
85 | __description("raw_stack: skb_load_bytes, no init") | |
86 | __success __retval(0) | |
87 | __naked void skb_load_bytes_no_init(void) | |
88 | { | |
89 | asm volatile (" \ | |
90 | r2 = 4; \ | |
91 | r6 = r10; \ | |
92 | r6 += -8; \ | |
93 | r3 = r6; \ | |
94 | r4 = 8; \ | |
95 | call %[bpf_skb_load_bytes]; \ | |
96 | r0 = *(u64*)(r6 + 0); \ | |
97 | exit; \ | |
98 | " : | |
99 | : __imm(bpf_skb_load_bytes) | |
100 | : __clobber_all); | |
101 | } | |
102 | ||
103 | SEC("tc") | |
104 | __description("raw_stack: skb_load_bytes, init") | |
105 | __success __retval(0) | |
106 | __naked void stack_skb_load_bytes_init(void) | |
107 | { | |
108 | asm volatile (" \ | |
109 | r2 = 4; \ | |
110 | r6 = r10; \ | |
111 | r6 += -8; \ | |
112 | r3 = 0xcafe; \ | |
113 | *(u64*)(r6 + 0) = r3; \ | |
114 | r3 = r6; \ | |
115 | r4 = 8; \ | |
116 | call %[bpf_skb_load_bytes]; \ | |
117 | r0 = *(u64*)(r6 + 0); \ | |
118 | exit; \ | |
119 | " : | |
120 | : __imm(bpf_skb_load_bytes) | |
121 | : __clobber_all); | |
122 | } | |
123 | ||
124 | SEC("tc") | |
125 | __description("raw_stack: skb_load_bytes, spilled regs around bounds") | |
126 | __success __retval(0) | |
127 | __naked void bytes_spilled_regs_around_bounds(void) | |
128 | { | |
129 | asm volatile (" \ | |
130 | r2 = 4; \ | |
131 | r6 = r10; \ | |
132 | r6 += -16; \ | |
133 | *(u64*)(r6 - 8) = r1; \ | |
134 | *(u64*)(r6 + 8) = r1; \ | |
135 | r3 = r6; \ | |
136 | r4 = 8; \ | |
137 | call %[bpf_skb_load_bytes]; \ | |
138 | r0 = *(u64*)(r6 - 8); \ | |
139 | r2 = *(u64*)(r6 + 8); \ | |
140 | r0 = *(u32*)(r0 + %[__sk_buff_mark]); \ | |
141 | r2 = *(u32*)(r2 + %[__sk_buff_priority]); \ | |
142 | r0 += r2; \ | |
143 | exit; \ | |
144 | " : | |
145 | : __imm(bpf_skb_load_bytes), | |
146 | __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), | |
147 | __imm_const(__sk_buff_priority, offsetof(struct __sk_buff, priority)) | |
148 | : __clobber_all); | |
149 | } | |
150 | ||
151 | SEC("tc") | |
152 | __description("raw_stack: skb_load_bytes, spilled regs corruption") | |
153 | __failure __msg("R0 invalid mem access 'scalar'") | |
154 | __flag(BPF_F_ANY_ALIGNMENT) | |
155 | __naked void load_bytes_spilled_regs_corruption(void) | |
156 | { | |
157 | asm volatile (" \ | |
158 | r2 = 4; \ | |
159 | r6 = r10; \ | |
160 | r6 += -8; \ | |
161 | *(u64*)(r6 + 0) = r1; \ | |
162 | r3 = r6; \ | |
163 | r4 = 8; \ | |
164 | call %[bpf_skb_load_bytes]; \ | |
165 | r0 = *(u64*)(r6 + 0); \ | |
166 | r0 = *(u32*)(r0 + %[__sk_buff_mark]); \ | |
167 | exit; \ | |
168 | " : | |
169 | : __imm(bpf_skb_load_bytes), | |
170 | __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) | |
171 | : __clobber_all); | |
172 | } | |
173 | ||
174 | SEC("tc") | |
175 | __description("raw_stack: skb_load_bytes, spilled regs corruption 2") | |
176 | __failure __msg("R3 invalid mem access 'scalar'") | |
177 | __flag(BPF_F_ANY_ALIGNMENT) | |
178 | __naked void bytes_spilled_regs_corruption_2(void) | |
179 | { | |
180 | asm volatile (" \ | |
181 | r2 = 4; \ | |
182 | r6 = r10; \ | |
183 | r6 += -16; \ | |
184 | *(u64*)(r6 - 8) = r1; \ | |
185 | *(u64*)(r6 + 0) = r1; \ | |
186 | *(u64*)(r6 + 8) = r1; \ | |
187 | r3 = r6; \ | |
188 | r4 = 8; \ | |
189 | call %[bpf_skb_load_bytes]; \ | |
190 | r0 = *(u64*)(r6 - 8); \ | |
191 | r2 = *(u64*)(r6 + 8); \ | |
192 | r3 = *(u64*)(r6 + 0); \ | |
193 | r0 = *(u32*)(r0 + %[__sk_buff_mark]); \ | |
194 | r2 = *(u32*)(r2 + %[__sk_buff_priority]); \ | |
195 | r0 += r2; \ | |
196 | r3 = *(u32*)(r3 + %[__sk_buff_pkt_type]); \ | |
197 | r0 += r3; \ | |
198 | exit; \ | |
199 | " : | |
200 | : __imm(bpf_skb_load_bytes), | |
201 | __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), | |
202 | __imm_const(__sk_buff_pkt_type, offsetof(struct __sk_buff, pkt_type)), | |
203 | __imm_const(__sk_buff_priority, offsetof(struct __sk_buff, priority)) | |
204 | : __clobber_all); | |
205 | } | |
206 | ||
207 | SEC("tc") | |
208 | __description("raw_stack: skb_load_bytes, spilled regs + data") | |
209 | __success __retval(0) | |
210 | __naked void load_bytes_spilled_regs_data(void) | |
211 | { | |
212 | asm volatile (" \ | |
213 | r2 = 4; \ | |
214 | r6 = r10; \ | |
215 | r6 += -16; \ | |
216 | *(u64*)(r6 - 8) = r1; \ | |
217 | *(u64*)(r6 + 0) = r1; \ | |
218 | *(u64*)(r6 + 8) = r1; \ | |
219 | r3 = r6; \ | |
220 | r4 = 8; \ | |
221 | call %[bpf_skb_load_bytes]; \ | |
222 | r0 = *(u64*)(r6 - 8); \ | |
223 | r2 = *(u64*)(r6 + 8); \ | |
224 | r3 = *(u64*)(r6 + 0); \ | |
225 | r0 = *(u32*)(r0 + %[__sk_buff_mark]); \ | |
226 | r2 = *(u32*)(r2 + %[__sk_buff_priority]); \ | |
227 | r0 += r2; \ | |
228 | r0 += r3; \ | |
229 | exit; \ | |
230 | " : | |
231 | : __imm(bpf_skb_load_bytes), | |
232 | __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), | |
233 | __imm_const(__sk_buff_priority, offsetof(struct __sk_buff, priority)) | |
234 | : __clobber_all); | |
235 | } | |
236 | ||
237 | SEC("tc") | |
238 | __description("raw_stack: skb_load_bytes, invalid access 1") | |
239 | __failure __msg("invalid indirect access to stack R3 off=-513 size=8") | |
240 | __naked void load_bytes_invalid_access_1(void) | |
241 | { | |
242 | asm volatile (" \ | |
243 | r2 = 4; \ | |
244 | r6 = r10; \ | |
245 | r6 += -513; \ | |
246 | r3 = r6; \ | |
247 | r4 = 8; \ | |
248 | call %[bpf_skb_load_bytes]; \ | |
249 | r0 = *(u64*)(r6 + 0); \ | |
250 | exit; \ | |
251 | " : | |
252 | : __imm(bpf_skb_load_bytes) | |
253 | : __clobber_all); | |
254 | } | |
255 | ||
256 | SEC("tc") | |
257 | __description("raw_stack: skb_load_bytes, invalid access 2") | |
258 | __failure __msg("invalid indirect access to stack R3 off=-1 size=8") | |
259 | __naked void load_bytes_invalid_access_2(void) | |
260 | { | |
261 | asm volatile (" \ | |
262 | r2 = 4; \ | |
263 | r6 = r10; \ | |
264 | r6 += -1; \ | |
265 | r3 = r6; \ | |
266 | r4 = 8; \ | |
267 | call %[bpf_skb_load_bytes]; \ | |
268 | r0 = *(u64*)(r6 + 0); \ | |
269 | exit; \ | |
270 | " : | |
271 | : __imm(bpf_skb_load_bytes) | |
272 | : __clobber_all); | |
273 | } | |
274 | ||
275 | SEC("tc") | |
276 | __description("raw_stack: skb_load_bytes, invalid access 3") | |
277 | __failure __msg("R4 min value is negative") | |
278 | __naked void load_bytes_invalid_access_3(void) | |
279 | { | |
280 | asm volatile (" \ | |
281 | r2 = 4; \ | |
282 | r6 = r10; \ | |
283 | r6 += 0xffffffff; \ | |
284 | r3 = r6; \ | |
285 | r4 = 0xffffffff; \ | |
286 | call %[bpf_skb_load_bytes]; \ | |
287 | r0 = *(u64*)(r6 + 0); \ | |
288 | exit; \ | |
289 | " : | |
290 | : __imm(bpf_skb_load_bytes) | |
291 | : __clobber_all); | |
292 | } | |
293 | ||
294 | SEC("tc") | |
295 | __description("raw_stack: skb_load_bytes, invalid access 4") | |
296 | __failure | |
297 | __msg("R4 unbounded memory access, use 'var &= const' or 'if (var < const)'") | |
298 | __naked void load_bytes_invalid_access_4(void) | |
299 | { | |
300 | asm volatile (" \ | |
301 | r2 = 4; \ | |
302 | r6 = r10; \ | |
303 | r6 += -1; \ | |
304 | r3 = r6; \ | |
305 | r4 = 0x7fffffff; \ | |
306 | call %[bpf_skb_load_bytes]; \ | |
307 | r0 = *(u64*)(r6 + 0); \ | |
308 | exit; \ | |
309 | " : | |
310 | : __imm(bpf_skb_load_bytes) | |
311 | : __clobber_all); | |
312 | } | |
313 | ||
314 | SEC("tc") | |
315 | __description("raw_stack: skb_load_bytes, invalid access 5") | |
316 | __failure | |
317 | __msg("R4 unbounded memory access, use 'var &= const' or 'if (var < const)'") | |
318 | __naked void load_bytes_invalid_access_5(void) | |
319 | { | |
320 | asm volatile (" \ | |
321 | r2 = 4; \ | |
322 | r6 = r10; \ | |
323 | r6 += -512; \ | |
324 | r3 = r6; \ | |
325 | r4 = 0x7fffffff; \ | |
326 | call %[bpf_skb_load_bytes]; \ | |
327 | r0 = *(u64*)(r6 + 0); \ | |
328 | exit; \ | |
329 | " : | |
330 | : __imm(bpf_skb_load_bytes) | |
331 | : __clobber_all); | |
332 | } | |
333 | ||
334 | SEC("tc") | |
335 | __description("raw_stack: skb_load_bytes, invalid access 6") | |
336 | __failure __msg("invalid zero-sized read") | |
337 | __naked void load_bytes_invalid_access_6(void) | |
338 | { | |
339 | asm volatile (" \ | |
340 | r2 = 4; \ | |
341 | r6 = r10; \ | |
342 | r6 += -512; \ | |
343 | r3 = r6; \ | |
344 | r4 = 0; \ | |
345 | call %[bpf_skb_load_bytes]; \ | |
346 | r0 = *(u64*)(r6 + 0); \ | |
347 | exit; \ | |
348 | " : | |
349 | : __imm(bpf_skb_load_bytes) | |
350 | : __clobber_all); | |
351 | } | |
352 | ||
353 | SEC("tc") | |
354 | __description("raw_stack: skb_load_bytes, large access") | |
355 | __success __retval(0) | |
356 | __naked void skb_load_bytes_large_access(void) | |
357 | { | |
358 | asm volatile (" \ | |
359 | r2 = 4; \ | |
360 | r6 = r10; \ | |
361 | r6 += -512; \ | |
362 | r3 = r6; \ | |
363 | r4 = 512; \ | |
364 | call %[bpf_skb_load_bytes]; \ | |
365 | r0 = *(u64*)(r6 + 0); \ | |
366 | exit; \ | |
367 | " : | |
368 | : __imm(bpf_skb_load_bytes) | |
369 | : __clobber_all); | |
370 | } | |
371 | ||
372 | char _license[] SEC("license") = "GPL"; |