1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Converted from tools/testing/selftests/bpf/verifier/value_ptr_arith.c */ |
3 | |
4 | #include <linux/bpf.h> |
5 | #include <bpf/bpf_helpers.h> |
6 | #include <errno.h> |
7 | #include "bpf_misc.h" |
8 | |
9 | #define MAX_ENTRIES 11 |
10 | |
11 | struct test_val { |
12 | unsigned int index; |
13 | int foo[MAX_ENTRIES]; |
14 | }; |
15 | |
16 | struct { |
17 | __uint(type, BPF_MAP_TYPE_ARRAY); |
18 | __uint(max_entries, 1); |
19 | __type(key, int); |
20 | __type(value, struct test_val); |
21 | } map_array_48b SEC(".maps" ); |
22 | |
23 | struct other_val { |
24 | long long foo; |
25 | long long bar; |
26 | }; |
27 | |
28 | struct { |
29 | __uint(type, BPF_MAP_TYPE_HASH); |
30 | __uint(max_entries, 1); |
31 | __type(key, long long); |
32 | __type(value, struct other_val); |
33 | } map_hash_16b SEC(".maps" ); |
34 | |
35 | struct { |
36 | __uint(type, BPF_MAP_TYPE_HASH); |
37 | __uint(max_entries, 1); |
38 | __type(key, long long); |
39 | __type(value, struct test_val); |
40 | } map_hash_48b SEC(".maps" ); |
41 | |
42 | SEC("socket" ) |
43 | __description("map access: known scalar += value_ptr unknown vs const" ) |
44 | __success __failure_unpriv |
45 | __msg_unpriv("R1 tried to add from different maps, paths or scalars" ) |
46 | __retval(1) |
47 | __naked void value_ptr_unknown_vs_const(void) |
48 | { |
49 | asm volatile (" \ |
50 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
51 | r1 = 0; \ |
52 | *(u64*)(r10 - 8) = r1; \ |
53 | r2 = r10; \ |
54 | r2 += -8; \ |
55 | if r0 == 1 goto l0_%=; \ |
56 | r1 = %[map_hash_16b] ll; \ |
57 | if r0 != 1 goto l1_%=; \ |
58 | l0_%=: r1 = %[map_array_48b] ll; \ |
59 | l1_%=: call %[bpf_map_lookup_elem]; \ |
60 | if r0 == 0 goto l2_%=; \ |
61 | r4 = *(u8*)(r0 + 0); \ |
62 | if r4 == 1 goto l3_%=; \ |
63 | r1 = 6; \ |
64 | r1 = -r1; \ |
65 | r1 &= 0x7; \ |
66 | goto l4_%=; \ |
67 | l3_%=: r1 = 3; \ |
68 | l4_%=: r1 += r0; \ |
69 | r0 = *(u8*)(r1 + 0); \ |
70 | l2_%=: r0 = 1; \ |
71 | exit; \ |
72 | " : |
73 | : __imm(bpf_map_lookup_elem), |
74 | __imm_addr(map_array_48b), |
75 | __imm_addr(map_hash_16b), |
76 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
77 | : __clobber_all); |
78 | } |
79 | |
80 | SEC("socket" ) |
81 | __description("map access: known scalar += value_ptr const vs unknown" ) |
82 | __success __failure_unpriv |
83 | __msg_unpriv("R1 tried to add from different maps, paths or scalars" ) |
84 | __retval(1) |
85 | __naked void value_ptr_const_vs_unknown(void) |
86 | { |
87 | asm volatile (" \ |
88 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
89 | r1 = 0; \ |
90 | *(u64*)(r10 - 8) = r1; \ |
91 | r2 = r10; \ |
92 | r2 += -8; \ |
93 | if r0 == 1 goto l0_%=; \ |
94 | r1 = %[map_hash_16b] ll; \ |
95 | if r0 != 1 goto l1_%=; \ |
96 | l0_%=: r1 = %[map_array_48b] ll; \ |
97 | l1_%=: call %[bpf_map_lookup_elem]; \ |
98 | if r0 == 0 goto l2_%=; \ |
99 | r4 = *(u8*)(r0 + 0); \ |
100 | if r4 == 1 goto l3_%=; \ |
101 | r1 = 3; \ |
102 | goto l4_%=; \ |
103 | l3_%=: r1 = 6; \ |
104 | r1 = -r1; \ |
105 | r1 &= 0x7; \ |
106 | l4_%=: r1 += r0; \ |
107 | r0 = *(u8*)(r1 + 0); \ |
108 | l2_%=: r0 = 1; \ |
109 | exit; \ |
110 | " : |
111 | : __imm(bpf_map_lookup_elem), |
112 | __imm_addr(map_array_48b), |
113 | __imm_addr(map_hash_16b), |
114 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
115 | : __clobber_all); |
116 | } |
117 | |
118 | SEC("socket" ) |
119 | __description("map access: known scalar += value_ptr const vs const (ne)" ) |
120 | __success __failure_unpriv |
121 | __msg_unpriv("R1 tried to add from different maps, paths or scalars" ) |
122 | __retval(1) |
123 | __naked void ptr_const_vs_const_ne(void) |
124 | { |
125 | asm volatile (" \ |
126 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
127 | r1 = 0; \ |
128 | *(u64*)(r10 - 8) = r1; \ |
129 | r2 = r10; \ |
130 | r2 += -8; \ |
131 | if r0 == 1 goto l0_%=; \ |
132 | r1 = %[map_hash_16b] ll; \ |
133 | if r0 != 1 goto l1_%=; \ |
134 | l0_%=: r1 = %[map_array_48b] ll; \ |
135 | l1_%=: call %[bpf_map_lookup_elem]; \ |
136 | if r0 == 0 goto l2_%=; \ |
137 | r4 = *(u8*)(r0 + 0); \ |
138 | if r4 == 1 goto l3_%=; \ |
139 | r1 = 3; \ |
140 | goto l4_%=; \ |
141 | l3_%=: r1 = 5; \ |
142 | l4_%=: r1 += r0; \ |
143 | r0 = *(u8*)(r1 + 0); \ |
144 | l2_%=: r0 = 1; \ |
145 | exit; \ |
146 | " : |
147 | : __imm(bpf_map_lookup_elem), |
148 | __imm_addr(map_array_48b), |
149 | __imm_addr(map_hash_16b), |
150 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
151 | : __clobber_all); |
152 | } |
153 | |
154 | SEC("socket" ) |
155 | __description("map access: known scalar += value_ptr const vs const (eq)" ) |
156 | __success __success_unpriv __retval(1) |
157 | __naked void ptr_const_vs_const_eq(void) |
158 | { |
159 | asm volatile (" \ |
160 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
161 | r1 = 0; \ |
162 | *(u64*)(r10 - 8) = r1; \ |
163 | r2 = r10; \ |
164 | r2 += -8; \ |
165 | if r0 == 1 goto l0_%=; \ |
166 | r1 = %[map_hash_16b] ll; \ |
167 | if r0 != 1 goto l1_%=; \ |
168 | l0_%=: r1 = %[map_array_48b] ll; \ |
169 | l1_%=: call %[bpf_map_lookup_elem]; \ |
170 | if r0 == 0 goto l2_%=; \ |
171 | r4 = *(u8*)(r0 + 0); \ |
172 | if r4 == 1 goto l3_%=; \ |
173 | r1 = 5; \ |
174 | goto l4_%=; \ |
175 | l3_%=: r1 = 5; \ |
176 | l4_%=: r1 += r0; \ |
177 | r0 = *(u8*)(r1 + 0); \ |
178 | l2_%=: r0 = 1; \ |
179 | exit; \ |
180 | " : |
181 | : __imm(bpf_map_lookup_elem), |
182 | __imm_addr(map_array_48b), |
183 | __imm_addr(map_hash_16b), |
184 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
185 | : __clobber_all); |
186 | } |
187 | |
188 | SEC("socket" ) |
189 | __description("map access: known scalar += value_ptr unknown vs unknown (eq)" ) |
190 | __success __success_unpriv __retval(1) |
191 | __naked void ptr_unknown_vs_unknown_eq(void) |
192 | { |
193 | asm volatile (" \ |
194 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
195 | r1 = 0; \ |
196 | *(u64*)(r10 - 8) = r1; \ |
197 | r2 = r10; \ |
198 | r2 += -8; \ |
199 | if r0 == 1 goto l0_%=; \ |
200 | r1 = %[map_hash_16b] ll; \ |
201 | if r0 != 1 goto l1_%=; \ |
202 | l0_%=: r1 = %[map_array_48b] ll; \ |
203 | l1_%=: call %[bpf_map_lookup_elem]; \ |
204 | if r0 == 0 goto l2_%=; \ |
205 | r4 = *(u8*)(r0 + 0); \ |
206 | if r4 == 1 goto l3_%=; \ |
207 | r1 = 6; \ |
208 | r1 = -r1; \ |
209 | r1 &= 0x7; \ |
210 | goto l4_%=; \ |
211 | l3_%=: r1 = 6; \ |
212 | r1 = -r1; \ |
213 | r1 &= 0x7; \ |
214 | l4_%=: r1 += r0; \ |
215 | r0 = *(u8*)(r1 + 0); \ |
216 | l2_%=: r0 = 1; \ |
217 | exit; \ |
218 | " : |
219 | : __imm(bpf_map_lookup_elem), |
220 | __imm_addr(map_array_48b), |
221 | __imm_addr(map_hash_16b), |
222 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
223 | : __clobber_all); |
224 | } |
225 | |
226 | SEC("socket" ) |
227 | __description("map access: known scalar += value_ptr unknown vs unknown (lt)" ) |
228 | __success __failure_unpriv |
229 | __msg_unpriv("R1 tried to add from different maps, paths or scalars" ) |
230 | __retval(1) |
231 | __naked void ptr_unknown_vs_unknown_lt(void) |
232 | { |
233 | asm volatile (" \ |
234 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
235 | r1 = 0; \ |
236 | *(u64*)(r10 - 8) = r1; \ |
237 | r2 = r10; \ |
238 | r2 += -8; \ |
239 | if r0 == 1 goto l0_%=; \ |
240 | r1 = %[map_hash_16b] ll; \ |
241 | if r0 != 1 goto l1_%=; \ |
242 | l0_%=: r1 = %[map_array_48b] ll; \ |
243 | l1_%=: call %[bpf_map_lookup_elem]; \ |
244 | if r0 == 0 goto l2_%=; \ |
245 | r4 = *(u8*)(r0 + 0); \ |
246 | if r4 == 1 goto l3_%=; \ |
247 | r1 = 6; \ |
248 | r1 = -r1; \ |
249 | r1 &= 0x3; \ |
250 | goto l4_%=; \ |
251 | l3_%=: r1 = 6; \ |
252 | r1 = -r1; \ |
253 | r1 &= 0x7; \ |
254 | l4_%=: r1 += r0; \ |
255 | r0 = *(u8*)(r1 + 0); \ |
256 | l2_%=: r0 = 1; \ |
257 | exit; \ |
258 | " : |
259 | : __imm(bpf_map_lookup_elem), |
260 | __imm_addr(map_array_48b), |
261 | __imm_addr(map_hash_16b), |
262 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
263 | : __clobber_all); |
264 | } |
265 | |
266 | SEC("socket" ) |
267 | __description("map access: known scalar += value_ptr unknown vs unknown (gt)" ) |
268 | __success __failure_unpriv |
269 | __msg_unpriv("R1 tried to add from different maps, paths or scalars" ) |
270 | __retval(1) |
271 | __naked void ptr_unknown_vs_unknown_gt(void) |
272 | { |
273 | asm volatile (" \ |
274 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
275 | r1 = 0; \ |
276 | *(u64*)(r10 - 8) = r1; \ |
277 | r2 = r10; \ |
278 | r2 += -8; \ |
279 | if r0 == 1 goto l0_%=; \ |
280 | r1 = %[map_hash_16b] ll; \ |
281 | if r0 != 1 goto l1_%=; \ |
282 | l0_%=: r1 = %[map_array_48b] ll; \ |
283 | l1_%=: call %[bpf_map_lookup_elem]; \ |
284 | if r0 == 0 goto l2_%=; \ |
285 | r4 = *(u8*)(r0 + 0); \ |
286 | if r4 == 1 goto l3_%=; \ |
287 | r1 = 6; \ |
288 | r1 = -r1; \ |
289 | r1 &= 0x7; \ |
290 | goto l4_%=; \ |
291 | l3_%=: r1 = 6; \ |
292 | r1 = -r1; \ |
293 | r1 &= 0x3; \ |
294 | l4_%=: r1 += r0; \ |
295 | r0 = *(u8*)(r1 + 0); \ |
296 | l2_%=: r0 = 1; \ |
297 | exit; \ |
298 | " : |
299 | : __imm(bpf_map_lookup_elem), |
300 | __imm_addr(map_array_48b), |
301 | __imm_addr(map_hash_16b), |
302 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
303 | : __clobber_all); |
304 | } |
305 | |
306 | SEC("socket" ) |
307 | __description("map access: known scalar += value_ptr from different maps" ) |
308 | __success __success_unpriv __retval(1) |
309 | __naked void value_ptr_from_different_maps(void) |
310 | { |
311 | asm volatile (" \ |
312 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
313 | r1 = 0; \ |
314 | *(u64*)(r10 - 8) = r1; \ |
315 | r2 = r10; \ |
316 | r2 += -8; \ |
317 | if r0 == 1 goto l0_%=; \ |
318 | r1 = %[map_hash_16b] ll; \ |
319 | if r0 != 1 goto l1_%=; \ |
320 | l0_%=: r1 = %[map_array_48b] ll; \ |
321 | l1_%=: call %[bpf_map_lookup_elem]; \ |
322 | if r0 == 0 goto l2_%=; \ |
323 | r1 = 4; \ |
324 | r1 += r0; \ |
325 | r0 = *(u8*)(r1 + 0); \ |
326 | l2_%=: r0 = 1; \ |
327 | exit; \ |
328 | " : |
329 | : __imm(bpf_map_lookup_elem), |
330 | __imm_addr(map_array_48b), |
331 | __imm_addr(map_hash_16b), |
332 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
333 | : __clobber_all); |
334 | } |
335 | |
336 | SEC("socket" ) |
337 | __description("map access: value_ptr -= known scalar from different maps" ) |
338 | __success __failure_unpriv |
339 | __msg_unpriv("R0 min value is outside of the allowed memory range" ) |
340 | __retval(1) |
341 | __naked void known_scalar_from_different_maps(void) |
342 | { |
343 | asm volatile (" \ |
344 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
345 | r1 = 0; \ |
346 | *(u64*)(r10 - 8) = r1; \ |
347 | r2 = r10; \ |
348 | r2 += -8; \ |
349 | if r0 == 1 goto l0_%=; \ |
350 | r1 = %[map_hash_16b] ll; \ |
351 | if r0 != 1 goto l1_%=; \ |
352 | l0_%=: r1 = %[map_array_48b] ll; \ |
353 | l1_%=: call %[bpf_map_lookup_elem]; \ |
354 | if r0 == 0 goto l2_%=; \ |
355 | r1 = 4; \ |
356 | r0 -= r1; \ |
357 | r0 += r1; \ |
358 | r0 = *(u8*)(r0 + 0); \ |
359 | l2_%=: r0 = 1; \ |
360 | exit; \ |
361 | " : |
362 | : __imm(bpf_map_lookup_elem), |
363 | __imm_addr(map_array_48b), |
364 | __imm_addr(map_hash_16b), |
365 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
366 | : __clobber_all); |
367 | } |
368 | |
369 | SEC("socket" ) |
370 | __description("map access: known scalar += value_ptr from different maps, but same value properties" ) |
371 | __success __success_unpriv __retval(1) |
372 | __naked void maps_but_same_value_properties(void) |
373 | { |
374 | asm volatile (" \ |
375 | r0 = *(u32*)(r1 + %[__sk_buff_len]); \ |
376 | r1 = 0; \ |
377 | *(u64*)(r10 - 8) = r1; \ |
378 | r2 = r10; \ |
379 | r2 += -8; \ |
380 | if r0 == 1 goto l0_%=; \ |
381 | r1 = %[map_hash_48b] ll; \ |
382 | if r0 != 1 goto l1_%=; \ |
383 | l0_%=: r1 = %[map_array_48b] ll; \ |
384 | l1_%=: call %[bpf_map_lookup_elem]; \ |
385 | if r0 == 0 goto l2_%=; \ |
386 | r1 = 4; \ |
387 | r1 += r0; \ |
388 | r0 = *(u8*)(r1 + 0); \ |
389 | l2_%=: r0 = 1; \ |
390 | exit; \ |
391 | " : |
392 | : __imm(bpf_map_lookup_elem), |
393 | __imm_addr(map_array_48b), |
394 | __imm_addr(map_hash_48b), |
395 | __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) |
396 | : __clobber_all); |
397 | } |
398 | |
399 | SEC("socket" ) |
400 | __description("map access: mixing value pointer and scalar, 1" ) |
401 | __success __failure_unpriv __msg_unpriv("R2 pointer comparison prohibited" ) |
402 | __retval(0) |
403 | __naked void value_pointer_and_scalar_1(void) |
404 | { |
405 | asm volatile (" \ |
406 | /* load map value pointer into r0 and r2 */ \ |
407 | r0 = 1; \ |
408 | r1 = %[map_array_48b] ll; \ |
409 | r2 = r10; \ |
410 | r2 += -16; \ |
411 | r6 = 0; \ |
412 | *(u64*)(r10 - 16) = r6; \ |
413 | call %[bpf_map_lookup_elem]; \ |
414 | if r0 != 0 goto l0_%=; \ |
415 | exit; \ |
416 | l0_%=: /* load some number from the map into r1 */ \ |
417 | r1 = *(u8*)(r0 + 0); \ |
418 | /* depending on r1, branch: */ \ |
419 | if r1 != 0 goto l1_%=; \ |
420 | /* branch A */ \ |
421 | r2 = r0; \ |
422 | r3 = 0; \ |
423 | goto l2_%=; \ |
424 | l1_%=: /* branch B */ \ |
425 | r2 = 0; \ |
426 | r3 = 0x100000; \ |
427 | l2_%=: /* common instruction */ \ |
428 | r2 += r3; \ |
429 | /* depending on r1, branch: */ \ |
430 | if r1 != 0 goto l3_%=; \ |
431 | /* branch A */ \ |
432 | goto l4_%=; \ |
433 | l3_%=: /* branch B */ \ |
434 | r0 = 0x13371337; \ |
435 | /* verifier follows fall-through */ \ |
436 | if r2 != 0x100000 goto l4_%=; \ |
437 | r0 = 0; \ |
438 | exit; \ |
439 | l4_%=: /* fake-dead code; targeted from branch A to \ |
440 | * prevent dead code sanitization \ |
441 | */ \ |
442 | r0 = *(u8*)(r0 + 0); \ |
443 | r0 = 0; \ |
444 | exit; \ |
445 | " : |
446 | : __imm(bpf_map_lookup_elem), |
447 | __imm_addr(map_array_48b) |
448 | : __clobber_all); |
449 | } |
450 | |
451 | SEC("socket" ) |
452 | __description("map access: mixing value pointer and scalar, 2" ) |
453 | __success __failure_unpriv __msg_unpriv("R0 invalid mem access 'scalar'" ) |
454 | __retval(0) |
455 | __naked void value_pointer_and_scalar_2(void) |
456 | { |
457 | asm volatile (" \ |
458 | /* load map value pointer into r0 and r2 */ \ |
459 | r0 = 1; \ |
460 | r1 = %[map_array_48b] ll; \ |
461 | r2 = r10; \ |
462 | r2 += -16; \ |
463 | r6 = 0; \ |
464 | *(u64*)(r10 - 16) = r6; \ |
465 | call %[bpf_map_lookup_elem]; \ |
466 | if r0 != 0 goto l0_%=; \ |
467 | exit; \ |
468 | l0_%=: /* load some number from the map into r1 */ \ |
469 | r1 = *(u8*)(r0 + 0); \ |
470 | /* depending on r1, branch: */ \ |
471 | if r1 == 0 goto l1_%=; \ |
472 | /* branch A */ \ |
473 | r2 = 0; \ |
474 | r3 = 0x100000; \ |
475 | goto l2_%=; \ |
476 | l1_%=: /* branch B */ \ |
477 | r2 = r0; \ |
478 | r3 = 0; \ |
479 | l2_%=: /* common instruction */ \ |
480 | r2 += r3; \ |
481 | /* depending on r1, branch: */ \ |
482 | if r1 != 0 goto l3_%=; \ |
483 | /* branch A */ \ |
484 | goto l4_%=; \ |
485 | l3_%=: /* branch B */ \ |
486 | r0 = 0x13371337; \ |
487 | /* verifier follows fall-through */ \ |
488 | if r2 != 0x100000 goto l4_%=; \ |
489 | r0 = 0; \ |
490 | exit; \ |
491 | l4_%=: /* fake-dead code; targeted from branch A to \ |
492 | * prevent dead code sanitization, rejected \ |
493 | * via branch B however \ |
494 | */ \ |
495 | r0 = *(u8*)(r0 + 0); \ |
496 | r0 = 0; \ |
497 | exit; \ |
498 | " : |
499 | : __imm(bpf_map_lookup_elem), |
500 | __imm_addr(map_array_48b) |
501 | : __clobber_all); |
502 | } |
503 | |
504 | SEC("socket" ) |
505 | __description("sanitation: alu with different scalars 1" ) |
506 | __success __success_unpriv __retval(0x100000) |
507 | __naked void alu_with_different_scalars_1(void) |
508 | { |
509 | asm volatile (" \ |
510 | r0 = 1; \ |
511 | r1 = %[map_array_48b] ll; \ |
512 | r2 = r10; \ |
513 | r2 += -16; \ |
514 | r6 = 0; \ |
515 | *(u64*)(r10 - 16) = r6; \ |
516 | call %[bpf_map_lookup_elem]; \ |
517 | if r0 != 0 goto l0_%=; \ |
518 | exit; \ |
519 | l0_%=: r1 = *(u32*)(r0 + 0); \ |
520 | if r1 == 0 goto l1_%=; \ |
521 | r2 = 0; \ |
522 | r3 = 0x100000; \ |
523 | goto l2_%=; \ |
524 | l1_%=: r2 = 42; \ |
525 | r3 = 0x100001; \ |
526 | l2_%=: r2 += r3; \ |
527 | r0 = r2; \ |
528 | exit; \ |
529 | " : |
530 | : __imm(bpf_map_lookup_elem), |
531 | __imm_addr(map_array_48b) |
532 | : __clobber_all); |
533 | } |
534 | |
535 | SEC("socket" ) |
536 | __description("sanitation: alu with different scalars 2" ) |
537 | __success __success_unpriv __retval(0) |
538 | __naked void alu_with_different_scalars_2(void) |
539 | { |
540 | asm volatile (" \ |
541 | r0 = 1; \ |
542 | r1 = %[map_array_48b] ll; \ |
543 | r6 = r1; \ |
544 | r2 = r10; \ |
545 | r2 += -16; \ |
546 | r7 = 0; \ |
547 | *(u64*)(r10 - 16) = r7; \ |
548 | call %[bpf_map_delete_elem]; \ |
549 | r7 = r0; \ |
550 | r1 = r6; \ |
551 | r2 = r10; \ |
552 | r2 += -16; \ |
553 | call %[bpf_map_delete_elem]; \ |
554 | r6 = r0; \ |
555 | r8 = r6; \ |
556 | r8 += r7; \ |
557 | r0 = r8; \ |
558 | r0 += %[einval]; \ |
559 | r0 += %[einval]; \ |
560 | exit; \ |
561 | " : |
562 | : __imm(bpf_map_delete_elem), |
563 | __imm_addr(map_array_48b), |
564 | __imm_const(einval, EINVAL) |
565 | : __clobber_all); |
566 | } |
567 | |
568 | SEC("socket" ) |
569 | __description("sanitation: alu with different scalars 3" ) |
570 | __success __success_unpriv __retval(0) |
571 | __naked void alu_with_different_scalars_3(void) |
572 | { |
573 | asm volatile (" \ |
574 | r0 = %[einval]; \ |
575 | r0 *= -1; \ |
576 | r7 = r0; \ |
577 | r0 = %[einval]; \ |
578 | r0 *= -1; \ |
579 | r6 = r0; \ |
580 | r8 = r6; \ |
581 | r8 += r7; \ |
582 | r0 = r8; \ |
583 | r0 += %[einval]; \ |
584 | r0 += %[einval]; \ |
585 | exit; \ |
586 | " : |
587 | : __imm_const(einval, EINVAL) |
588 | : __clobber_all); |
589 | } |
590 | |
591 | SEC("socket" ) |
592 | __description("map access: value_ptr += known scalar, upper oob arith, test 1" ) |
593 | __success __failure_unpriv |
594 | __msg_unpriv("R0 pointer arithmetic of map value goes out of range" ) |
595 | __retval(1) |
596 | __naked void upper_oob_arith_test_1(void) |
597 | { |
598 | asm volatile (" \ |
599 | r1 = 0; \ |
600 | *(u64*)(r10 - 8) = r1; \ |
601 | r2 = r10; \ |
602 | r2 += -8; \ |
603 | r1 = %[map_array_48b] ll; \ |
604 | call %[bpf_map_lookup_elem]; \ |
605 | if r0 == 0 goto l0_%=; \ |
606 | r1 = 48; \ |
607 | r0 += r1; \ |
608 | r0 -= r1; \ |
609 | r0 = *(u8*)(r0 + 0); \ |
610 | l0_%=: r0 = 1; \ |
611 | exit; \ |
612 | " : |
613 | : __imm(bpf_map_lookup_elem), |
614 | __imm_addr(map_array_48b) |
615 | : __clobber_all); |
616 | } |
617 | |
618 | SEC("socket" ) |
619 | __description("map access: value_ptr += known scalar, upper oob arith, test 2" ) |
620 | __success __failure_unpriv |
621 | __msg_unpriv("R0 pointer arithmetic of map value goes out of range" ) |
622 | __retval(1) |
623 | __naked void upper_oob_arith_test_2(void) |
624 | { |
625 | asm volatile (" \ |
626 | r1 = 0; \ |
627 | *(u64*)(r10 - 8) = r1; \ |
628 | r2 = r10; \ |
629 | r2 += -8; \ |
630 | r1 = %[map_array_48b] ll; \ |
631 | call %[bpf_map_lookup_elem]; \ |
632 | if r0 == 0 goto l0_%=; \ |
633 | r1 = 49; \ |
634 | r0 += r1; \ |
635 | r0 -= r1; \ |
636 | r0 = *(u8*)(r0 + 0); \ |
637 | l0_%=: r0 = 1; \ |
638 | exit; \ |
639 | " : |
640 | : __imm(bpf_map_lookup_elem), |
641 | __imm_addr(map_array_48b) |
642 | : __clobber_all); |
643 | } |
644 | |
645 | SEC("socket" ) |
646 | __description("map access: value_ptr += known scalar, upper oob arith, test 3" ) |
647 | __success __success_unpriv __retval(1) |
648 | __naked void upper_oob_arith_test_3(void) |
649 | { |
650 | asm volatile (" \ |
651 | r1 = 0; \ |
652 | *(u64*)(r10 - 8) = r1; \ |
653 | r2 = r10; \ |
654 | r2 += -8; \ |
655 | r1 = %[map_array_48b] ll; \ |
656 | call %[bpf_map_lookup_elem]; \ |
657 | if r0 == 0 goto l0_%=; \ |
658 | r1 = 47; \ |
659 | r0 += r1; \ |
660 | r0 -= r1; \ |
661 | r0 = *(u8*)(r0 + 0); \ |
662 | l0_%=: r0 = 1; \ |
663 | exit; \ |
664 | " : |
665 | : __imm(bpf_map_lookup_elem), |
666 | __imm_addr(map_array_48b) |
667 | : __clobber_all); |
668 | } |
669 | |
670 | SEC("socket" ) |
671 | __description("map access: value_ptr -= known scalar, lower oob arith, test 1" ) |
672 | __failure __msg("R0 min value is outside of the allowed memory range" ) |
673 | __failure_unpriv |
674 | __msg_unpriv("R0 pointer arithmetic of map value goes out of range" ) |
675 | __naked void lower_oob_arith_test_1(void) |
676 | { |
677 | asm volatile (" \ |
678 | r1 = 0; \ |
679 | *(u64*)(r10 - 8) = r1; \ |
680 | r2 = r10; \ |
681 | r2 += -8; \ |
682 | r1 = %[map_array_48b] ll; \ |
683 | call %[bpf_map_lookup_elem]; \ |
684 | if r0 == 0 goto l0_%=; \ |
685 | r1 = 47; \ |
686 | r0 += r1; \ |
687 | r1 = 48; \ |
688 | r0 -= r1; \ |
689 | r0 = *(u8*)(r0 + 0); \ |
690 | l0_%=: r0 = 1; \ |
691 | exit; \ |
692 | " : |
693 | : __imm(bpf_map_lookup_elem), |
694 | __imm_addr(map_array_48b) |
695 | : __clobber_all); |
696 | } |
697 | |
698 | SEC("socket" ) |
699 | __description("map access: value_ptr -= known scalar, lower oob arith, test 2" ) |
700 | __success __failure_unpriv |
701 | __msg_unpriv("R0 pointer arithmetic of map value goes out of range" ) |
702 | __retval(1) |
703 | __naked void lower_oob_arith_test_2(void) |
704 | { |
705 | asm volatile (" \ |
706 | r1 = 0; \ |
707 | *(u64*)(r10 - 8) = r1; \ |
708 | r2 = r10; \ |
709 | r2 += -8; \ |
710 | r1 = %[map_array_48b] ll; \ |
711 | call %[bpf_map_lookup_elem]; \ |
712 | if r0 == 0 goto l0_%=; \ |
713 | r1 = 47; \ |
714 | r0 += r1; \ |
715 | r1 = 48; \ |
716 | r0 -= r1; \ |
717 | r1 = 1; \ |
718 | r0 += r1; \ |
719 | r0 = *(u8*)(r0 + 0); \ |
720 | l0_%=: r0 = 1; \ |
721 | exit; \ |
722 | " : |
723 | : __imm(bpf_map_lookup_elem), |
724 | __imm_addr(map_array_48b) |
725 | : __clobber_all); |
726 | } |
727 | |
728 | SEC("socket" ) |
729 | __description("map access: value_ptr -= known scalar, lower oob arith, test 3" ) |
730 | __success __success_unpriv __retval(1) |
731 | __naked void lower_oob_arith_test_3(void) |
732 | { |
733 | asm volatile (" \ |
734 | r1 = 0; \ |
735 | *(u64*)(r10 - 8) = r1; \ |
736 | r2 = r10; \ |
737 | r2 += -8; \ |
738 | r1 = %[map_array_48b] ll; \ |
739 | call %[bpf_map_lookup_elem]; \ |
740 | if r0 == 0 goto l0_%=; \ |
741 | r1 = 47; \ |
742 | r0 += r1; \ |
743 | r1 = 47; \ |
744 | r0 -= r1; \ |
745 | r0 = *(u8*)(r0 + 0); \ |
746 | l0_%=: r0 = 1; \ |
747 | exit; \ |
748 | " : |
749 | : __imm(bpf_map_lookup_elem), |
750 | __imm_addr(map_array_48b) |
751 | : __clobber_all); |
752 | } |
753 | |
754 | SEC("socket" ) |
755 | __description("map access: known scalar += value_ptr" ) |
756 | __success __success_unpriv __retval(1) |
757 | __naked void access_known_scalar_value_ptr_1(void) |
758 | { |
759 | asm volatile (" \ |
760 | r1 = 0; \ |
761 | *(u64*)(r10 - 8) = r1; \ |
762 | r2 = r10; \ |
763 | r2 += -8; \ |
764 | r1 = %[map_array_48b] ll; \ |
765 | call %[bpf_map_lookup_elem]; \ |
766 | if r0 == 0 goto l0_%=; \ |
767 | r1 = 4; \ |
768 | r1 += r0; \ |
769 | r0 = *(u8*)(r1 + 0); \ |
770 | l0_%=: r0 = 1; \ |
771 | exit; \ |
772 | " : |
773 | : __imm(bpf_map_lookup_elem), |
774 | __imm_addr(map_array_48b) |
775 | : __clobber_all); |
776 | } |
777 | |
778 | SEC("socket" ) |
779 | __description("map access: value_ptr += known scalar, 1" ) |
780 | __success __success_unpriv __retval(1) |
781 | __naked void value_ptr_known_scalar_1(void) |
782 | { |
783 | asm volatile (" \ |
784 | r1 = 0; \ |
785 | *(u64*)(r10 - 8) = r1; \ |
786 | r2 = r10; \ |
787 | r2 += -8; \ |
788 | r1 = %[map_array_48b] ll; \ |
789 | call %[bpf_map_lookup_elem]; \ |
790 | if r0 == 0 goto l0_%=; \ |
791 | r1 = 4; \ |
792 | r0 += r1; \ |
793 | r1 = *(u8*)(r0 + 0); \ |
794 | l0_%=: r0 = 1; \ |
795 | exit; \ |
796 | " : |
797 | : __imm(bpf_map_lookup_elem), |
798 | __imm_addr(map_array_48b) |
799 | : __clobber_all); |
800 | } |
801 | |
802 | SEC("socket" ) |
803 | __description("map access: value_ptr += known scalar, 2" ) |
804 | __failure __msg("invalid access to map value" ) |
805 | __failure_unpriv |
806 | __naked void value_ptr_known_scalar_2_1(void) |
807 | { |
808 | asm volatile (" \ |
809 | r1 = 0; \ |
810 | *(u64*)(r10 - 8) = r1; \ |
811 | r2 = r10; \ |
812 | r2 += -8; \ |
813 | r1 = %[map_array_48b] ll; \ |
814 | call %[bpf_map_lookup_elem]; \ |
815 | if r0 == 0 goto l0_%=; \ |
816 | r1 = 49; \ |
817 | r0 += r1; \ |
818 | r1 = *(u8*)(r0 + 0); \ |
819 | l0_%=: r0 = 1; \ |
820 | exit; \ |
821 | " : |
822 | : __imm(bpf_map_lookup_elem), |
823 | __imm_addr(map_array_48b) |
824 | : __clobber_all); |
825 | } |
826 | |
827 | SEC("socket" ) |
828 | __description("map access: value_ptr += known scalar, 3" ) |
829 | __failure __msg("invalid access to map value" ) |
830 | __failure_unpriv |
831 | __naked void value_ptr_known_scalar_3(void) |
832 | { |
833 | asm volatile (" \ |
834 | r1 = 0; \ |
835 | *(u64*)(r10 - 8) = r1; \ |
836 | r2 = r10; \ |
837 | r2 += -8; \ |
838 | r1 = %[map_array_48b] ll; \ |
839 | call %[bpf_map_lookup_elem]; \ |
840 | if r0 == 0 goto l0_%=; \ |
841 | r1 = -1; \ |
842 | r0 += r1; \ |
843 | r1 = *(u8*)(r0 + 0); \ |
844 | l0_%=: r0 = 1; \ |
845 | exit; \ |
846 | " : |
847 | : __imm(bpf_map_lookup_elem), |
848 | __imm_addr(map_array_48b) |
849 | : __clobber_all); |
850 | } |
851 | |
852 | SEC("socket" ) |
853 | __description("map access: value_ptr += known scalar, 4" ) |
854 | __success __success_unpriv __retval(1) |
855 | __naked void value_ptr_known_scalar_4(void) |
856 | { |
857 | asm volatile (" \ |
858 | r1 = 0; \ |
859 | *(u64*)(r10 - 8) = r1; \ |
860 | r2 = r10; \ |
861 | r2 += -8; \ |
862 | r1 = %[map_array_48b] ll; \ |
863 | call %[bpf_map_lookup_elem]; \ |
864 | if r0 == 0 goto l0_%=; \ |
865 | r1 = 5; \ |
866 | r0 += r1; \ |
867 | r1 = -2; \ |
868 | r0 += r1; \ |
869 | r1 = -1; \ |
870 | r0 += r1; \ |
871 | r1 = *(u8*)(r0 + 0); \ |
872 | l0_%=: r0 = 1; \ |
873 | exit; \ |
874 | " : |
875 | : __imm(bpf_map_lookup_elem), |
876 | __imm_addr(map_array_48b) |
877 | : __clobber_all); |
878 | } |
879 | |
880 | SEC("socket" ) |
881 | __description("map access: value_ptr += known scalar, 5" ) |
882 | __success __success_unpriv __retval(0xabcdef12) |
883 | __naked void value_ptr_known_scalar_5(void) |
884 | { |
885 | asm volatile (" \ |
886 | r1 = 0; \ |
887 | *(u64*)(r10 - 8) = r1; \ |
888 | r2 = r10; \ |
889 | r2 += -8; \ |
890 | r1 = %[map_array_48b] ll; \ |
891 | call %[bpf_map_lookup_elem]; \ |
892 | if r0 == 0 goto l0_%=; \ |
893 | r1 = %[__imm_0]; \ |
894 | r1 += r0; \ |
895 | r0 = *(u32*)(r1 + 0); \ |
896 | l0_%=: exit; \ |
897 | " : |
898 | : __imm(bpf_map_lookup_elem), |
899 | __imm_addr(map_array_48b), |
900 | __imm_const(__imm_0, (6 + 1) * sizeof(int)) |
901 | : __clobber_all); |
902 | } |
903 | |
904 | SEC("socket" ) |
905 | __description("map access: value_ptr += known scalar, 6" ) |
906 | __success __success_unpriv __retval(0xabcdef12) |
907 | __naked void value_ptr_known_scalar_6(void) |
908 | { |
909 | asm volatile (" \ |
910 | r1 = 0; \ |
911 | *(u64*)(r10 - 8) = r1; \ |
912 | r2 = r10; \ |
913 | r2 += -8; \ |
914 | r1 = %[map_array_48b] ll; \ |
915 | call %[bpf_map_lookup_elem]; \ |
916 | if r0 == 0 goto l0_%=; \ |
917 | r1 = %[__imm_0]; \ |
918 | r0 += r1; \ |
919 | r1 = %[__imm_1]; \ |
920 | r0 += r1; \ |
921 | r0 = *(u32*)(r0 + 0); \ |
922 | l0_%=: exit; \ |
923 | " : |
924 | : __imm(bpf_map_lookup_elem), |
925 | __imm_addr(map_array_48b), |
926 | __imm_const(__imm_0, (3 + 1) * sizeof(int)), |
927 | __imm_const(__imm_1, 3 * sizeof(int)) |
928 | : __clobber_all); |
929 | } |
930 | |
931 | SEC("socket" ) |
932 | __description("map access: value_ptr += N, value_ptr -= N known scalar" ) |
933 | __success __success_unpriv __retval(0x12345678) |
934 | __naked void value_ptr_n_known_scalar(void) |
935 | { |
936 | asm volatile (" \ |
937 | r1 = 0; \ |
938 | *(u64*)(r10 - 8) = r1; \ |
939 | r2 = r10; \ |
940 | r2 += -8; \ |
941 | r1 = %[map_array_48b] ll; \ |
942 | call %[bpf_map_lookup_elem]; \ |
943 | if r0 == 0 goto l0_%=; \ |
944 | w1 = 0x12345678; \ |
945 | *(u32*)(r0 + 0) = r1; \ |
946 | r0 += 2; \ |
947 | r1 = 2; \ |
948 | r0 -= r1; \ |
949 | r0 = *(u32*)(r0 + 0); \ |
950 | l0_%=: exit; \ |
951 | " : |
952 | : __imm(bpf_map_lookup_elem), |
953 | __imm_addr(map_array_48b) |
954 | : __clobber_all); |
955 | } |
956 | |
957 | SEC("socket" ) |
958 | __description("map access: unknown scalar += value_ptr, 1" ) |
959 | __success __success_unpriv __retval(1) |
960 | __naked void unknown_scalar_value_ptr_1(void) |
961 | { |
962 | asm volatile (" \ |
963 | r1 = 0; \ |
964 | *(u64*)(r10 - 8) = r1; \ |
965 | r2 = r10; \ |
966 | r2 += -8; \ |
967 | r1 = %[map_array_48b] ll; \ |
968 | call %[bpf_map_lookup_elem]; \ |
969 | if r0 == 0 goto l0_%=; \ |
970 | r1 = *(u8*)(r0 + 0); \ |
971 | r1 &= 0xf; \ |
972 | r1 += r0; \ |
973 | r0 = *(u8*)(r1 + 0); \ |
974 | l0_%=: r0 = 1; \ |
975 | exit; \ |
976 | " : |
977 | : __imm(bpf_map_lookup_elem), |
978 | __imm_addr(map_array_48b) |
979 | : __clobber_all); |
980 | } |
981 | |
982 | SEC("socket" ) |
983 | __description("map access: unknown scalar += value_ptr, 2" ) |
984 | __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT) |
985 | __naked void unknown_scalar_value_ptr_2(void) |
986 | { |
987 | asm volatile (" \ |
988 | r1 = 0; \ |
989 | *(u64*)(r10 - 8) = r1; \ |
990 | r2 = r10; \ |
991 | r2 += -8; \ |
992 | r1 = %[map_array_48b] ll; \ |
993 | call %[bpf_map_lookup_elem]; \ |
994 | if r0 == 0 goto l0_%=; \ |
995 | r1 = *(u32*)(r0 + 0); \ |
996 | r1 &= 31; \ |
997 | r1 += r0; \ |
998 | r0 = *(u32*)(r1 + 0); \ |
999 | l0_%=: exit; \ |
1000 | " : |
1001 | : __imm(bpf_map_lookup_elem), |
1002 | __imm_addr(map_array_48b) |
1003 | : __clobber_all); |
1004 | } |
1005 | |
1006 | SEC("socket" ) |
1007 | __description("map access: unknown scalar += value_ptr, 3" ) |
1008 | __success __failure_unpriv |
1009 | __msg_unpriv("R0 pointer arithmetic of map value goes out of range" ) |
1010 | __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT) |
1011 | __naked void unknown_scalar_value_ptr_3(void) |
1012 | { |
1013 | asm volatile (" \ |
1014 | r1 = 0; \ |
1015 | *(u64*)(r10 - 8) = r1; \ |
1016 | r2 = r10; \ |
1017 | r2 += -8; \ |
1018 | r1 = %[map_array_48b] ll; \ |
1019 | call %[bpf_map_lookup_elem]; \ |
1020 | if r0 == 0 goto l0_%=; \ |
1021 | r1 = -1; \ |
1022 | r0 += r1; \ |
1023 | r1 = 1; \ |
1024 | r0 += r1; \ |
1025 | r1 = *(u32*)(r0 + 0); \ |
1026 | r1 &= 31; \ |
1027 | r1 += r0; \ |
1028 | r0 = *(u32*)(r1 + 0); \ |
1029 | l0_%=: exit; \ |
1030 | " : |
1031 | : __imm(bpf_map_lookup_elem), |
1032 | __imm_addr(map_array_48b) |
1033 | : __clobber_all); |
1034 | } |
1035 | |
1036 | SEC("socket" ) |
1037 | __description("map access: unknown scalar += value_ptr, 4" ) |
1038 | __failure __msg("R1 max value is outside of the allowed memory range" ) |
1039 | __msg_unpriv("R1 pointer arithmetic of map value goes out of range" ) |
1040 | __flag(BPF_F_ANY_ALIGNMENT) |
1041 | __naked void unknown_scalar_value_ptr_4(void) |
1042 | { |
1043 | asm volatile (" \ |
1044 | r1 = 0; \ |
1045 | *(u64*)(r10 - 8) = r1; \ |
1046 | r2 = r10; \ |
1047 | r2 += -8; \ |
1048 | r1 = %[map_array_48b] ll; \ |
1049 | call %[bpf_map_lookup_elem]; \ |
1050 | if r0 == 0 goto l0_%=; \ |
1051 | r1 = 19; \ |
1052 | r0 += r1; \ |
1053 | r1 = *(u32*)(r0 + 0); \ |
1054 | r1 &= 31; \ |
1055 | r1 += r0; \ |
1056 | r0 = *(u32*)(r1 + 0); \ |
1057 | l0_%=: exit; \ |
1058 | " : |
1059 | : __imm(bpf_map_lookup_elem), |
1060 | __imm_addr(map_array_48b) |
1061 | : __clobber_all); |
1062 | } |
1063 | |
1064 | SEC("socket" ) |
1065 | __description("map access: value_ptr += unknown scalar, 1" ) |
1066 | __success __success_unpriv __retval(1) |
1067 | __naked void value_ptr_unknown_scalar_1(void) |
1068 | { |
1069 | asm volatile (" \ |
1070 | r1 = 0; \ |
1071 | *(u64*)(r10 - 8) = r1; \ |
1072 | r2 = r10; \ |
1073 | r2 += -8; \ |
1074 | r1 = %[map_array_48b] ll; \ |
1075 | call %[bpf_map_lookup_elem]; \ |
1076 | if r0 == 0 goto l0_%=; \ |
1077 | r1 = *(u8*)(r0 + 0); \ |
1078 | r1 &= 0xf; \ |
1079 | r0 += r1; \ |
1080 | r1 = *(u8*)(r0 + 0); \ |
1081 | l0_%=: r0 = 1; \ |
1082 | exit; \ |
1083 | " : |
1084 | : __imm(bpf_map_lookup_elem), |
1085 | __imm_addr(map_array_48b) |
1086 | : __clobber_all); |
1087 | } |
1088 | |
1089 | SEC("socket" ) |
1090 | __description("map access: value_ptr += unknown scalar, 2" ) |
1091 | __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT) |
1092 | __naked void value_ptr_unknown_scalar_2_1(void) |
1093 | { |
1094 | asm volatile (" \ |
1095 | r1 = 0; \ |
1096 | *(u64*)(r10 - 8) = r1; \ |
1097 | r2 = r10; \ |
1098 | r2 += -8; \ |
1099 | r1 = %[map_array_48b] ll; \ |
1100 | call %[bpf_map_lookup_elem]; \ |
1101 | if r0 == 0 goto l0_%=; \ |
1102 | r1 = *(u32*)(r0 + 0); \ |
1103 | r1 &= 31; \ |
1104 | r0 += r1; \ |
1105 | r0 = *(u32*)(r0 + 0); \ |
1106 | l0_%=: exit; \ |
1107 | " : |
1108 | : __imm(bpf_map_lookup_elem), |
1109 | __imm_addr(map_array_48b) |
1110 | : __clobber_all); |
1111 | } |
1112 | |
1113 | SEC("socket" ) |
1114 | __description("map access: value_ptr += unknown scalar, 3" ) |
1115 | __success __success_unpriv __retval(1) |
1116 | __naked void value_ptr_unknown_scalar_3(void) |
1117 | { |
1118 | asm volatile (" \ |
1119 | r1 = 0; \ |
1120 | *(u64*)(r10 - 8) = r1; \ |
1121 | r2 = r10; \ |
1122 | r2 += -8; \ |
1123 | r1 = %[map_array_48b] ll; \ |
1124 | call %[bpf_map_lookup_elem]; \ |
1125 | if r0 == 0 goto l0_%=; \ |
1126 | r1 = *(u64*)(r0 + 0); \ |
1127 | r2 = *(u64*)(r0 + 8); \ |
1128 | r3 = *(u64*)(r0 + 16); \ |
1129 | r1 &= 0xf; \ |
1130 | r3 &= 1; \ |
1131 | r3 |= 1; \ |
1132 | if r2 > r3 goto l0_%=; \ |
1133 | r0 += r3; \ |
1134 | r0 = *(u8*)(r0 + 0); \ |
1135 | r0 = 1; \ |
1136 | l1_%=: exit; \ |
1137 | l0_%=: r0 = 2; \ |
1138 | goto l1_%=; \ |
1139 | " : |
1140 | : __imm(bpf_map_lookup_elem), |
1141 | __imm_addr(map_array_48b) |
1142 | : __clobber_all); |
1143 | } |
1144 | |
1145 | SEC("socket" ) |
1146 | __description("map access: value_ptr += value_ptr" ) |
1147 | __failure __msg("R0 pointer += pointer prohibited" ) |
1148 | __failure_unpriv |
1149 | __naked void access_value_ptr_value_ptr_1(void) |
1150 | { |
1151 | asm volatile (" \ |
1152 | r1 = 0; \ |
1153 | *(u64*)(r10 - 8) = r1; \ |
1154 | r2 = r10; \ |
1155 | r2 += -8; \ |
1156 | r1 = %[map_array_48b] ll; \ |
1157 | call %[bpf_map_lookup_elem]; \ |
1158 | if r0 == 0 goto l0_%=; \ |
1159 | r0 += r0; \ |
1160 | r1 = *(u8*)(r0 + 0); \ |
1161 | l0_%=: r0 = 1; \ |
1162 | exit; \ |
1163 | " : |
1164 | : __imm(bpf_map_lookup_elem), |
1165 | __imm_addr(map_array_48b) |
1166 | : __clobber_all); |
1167 | } |
1168 | |
1169 | SEC("socket" ) |
1170 | __description("map access: known scalar -= value_ptr" ) |
1171 | __failure __msg("R1 tried to subtract pointer from scalar" ) |
1172 | __failure_unpriv |
1173 | __naked void access_known_scalar_value_ptr_2(void) |
1174 | { |
1175 | asm volatile (" \ |
1176 | r1 = 0; \ |
1177 | *(u64*)(r10 - 8) = r1; \ |
1178 | r2 = r10; \ |
1179 | r2 += -8; \ |
1180 | r1 = %[map_array_48b] ll; \ |
1181 | call %[bpf_map_lookup_elem]; \ |
1182 | if r0 == 0 goto l0_%=; \ |
1183 | r1 = 4; \ |
1184 | r1 -= r0; \ |
1185 | r0 = *(u8*)(r1 + 0); \ |
1186 | l0_%=: r0 = 1; \ |
1187 | exit; \ |
1188 | " : |
1189 | : __imm(bpf_map_lookup_elem), |
1190 | __imm_addr(map_array_48b) |
1191 | : __clobber_all); |
1192 | } |
1193 | |
1194 | SEC("socket" ) |
1195 | __description("map access: value_ptr -= known scalar" ) |
1196 | __failure __msg("R0 min value is outside of the allowed memory range" ) |
1197 | __failure_unpriv |
1198 | __naked void access_value_ptr_known_scalar(void) |
1199 | { |
1200 | asm volatile (" \ |
1201 | r1 = 0; \ |
1202 | *(u64*)(r10 - 8) = r1; \ |
1203 | r2 = r10; \ |
1204 | r2 += -8; \ |
1205 | r1 = %[map_array_48b] ll; \ |
1206 | call %[bpf_map_lookup_elem]; \ |
1207 | if r0 == 0 goto l0_%=; \ |
1208 | r1 = 4; \ |
1209 | r0 -= r1; \ |
1210 | r1 = *(u8*)(r0 + 0); \ |
1211 | l0_%=: r0 = 1; \ |
1212 | exit; \ |
1213 | " : |
1214 | : __imm(bpf_map_lookup_elem), |
1215 | __imm_addr(map_array_48b) |
1216 | : __clobber_all); |
1217 | } |
1218 | |
1219 | SEC("socket" ) |
1220 | __description("map access: value_ptr -= known scalar, 2" ) |
1221 | __success __success_unpriv __retval(1) |
1222 | __naked void value_ptr_known_scalar_2_2(void) |
1223 | { |
1224 | asm volatile (" \ |
1225 | r1 = 0; \ |
1226 | *(u64*)(r10 - 8) = r1; \ |
1227 | r2 = r10; \ |
1228 | r2 += -8; \ |
1229 | r1 = %[map_array_48b] ll; \ |
1230 | call %[bpf_map_lookup_elem]; \ |
1231 | if r0 == 0 goto l0_%=; \ |
1232 | r1 = 6; \ |
1233 | r2 = 4; \ |
1234 | r0 += r1; \ |
1235 | r0 -= r2; \ |
1236 | r1 = *(u8*)(r0 + 0); \ |
1237 | l0_%=: r0 = 1; \ |
1238 | exit; \ |
1239 | " : |
1240 | : __imm(bpf_map_lookup_elem), |
1241 | __imm_addr(map_array_48b) |
1242 | : __clobber_all); |
1243 | } |
1244 | |
1245 | SEC("socket" ) |
1246 | __description("map access: unknown scalar -= value_ptr" ) |
1247 | __failure __msg("R1 tried to subtract pointer from scalar" ) |
1248 | __failure_unpriv |
1249 | __naked void access_unknown_scalar_value_ptr(void) |
1250 | { |
1251 | asm volatile (" \ |
1252 | r1 = 0; \ |
1253 | *(u64*)(r10 - 8) = r1; \ |
1254 | r2 = r10; \ |
1255 | r2 += -8; \ |
1256 | r1 = %[map_array_48b] ll; \ |
1257 | call %[bpf_map_lookup_elem]; \ |
1258 | if r0 == 0 goto l0_%=; \ |
1259 | r1 = *(u8*)(r0 + 0); \ |
1260 | r1 &= 0xf; \ |
1261 | r1 -= r0; \ |
1262 | r0 = *(u8*)(r1 + 0); \ |
1263 | l0_%=: r0 = 1; \ |
1264 | exit; \ |
1265 | " : |
1266 | : __imm(bpf_map_lookup_elem), |
1267 | __imm_addr(map_array_48b) |
1268 | : __clobber_all); |
1269 | } |
1270 | |
1271 | SEC("socket" ) |
1272 | __description("map access: value_ptr -= unknown scalar" ) |
1273 | __failure __msg("R0 min value is negative" ) |
1274 | __failure_unpriv |
1275 | __naked void access_value_ptr_unknown_scalar(void) |
1276 | { |
1277 | asm volatile (" \ |
1278 | r1 = 0; \ |
1279 | *(u64*)(r10 - 8) = r1; \ |
1280 | r2 = r10; \ |
1281 | r2 += -8; \ |
1282 | r1 = %[map_array_48b] ll; \ |
1283 | call %[bpf_map_lookup_elem]; \ |
1284 | if r0 == 0 goto l0_%=; \ |
1285 | r1 = *(u8*)(r0 + 0); \ |
1286 | r1 &= 0xf; \ |
1287 | r0 -= r1; \ |
1288 | r1 = *(u8*)(r0 + 0); \ |
1289 | l0_%=: r0 = 1; \ |
1290 | exit; \ |
1291 | " : |
1292 | : __imm(bpf_map_lookup_elem), |
1293 | __imm_addr(map_array_48b) |
1294 | : __clobber_all); |
1295 | } |
1296 | |
1297 | SEC("socket" ) |
1298 | __description("map access: value_ptr -= unknown scalar, 2" ) |
1299 | __success __failure_unpriv |
1300 | __msg_unpriv("R0 pointer arithmetic of map value goes out of range" ) |
1301 | __retval(1) |
1302 | __naked void value_ptr_unknown_scalar_2_2(void) |
1303 | { |
1304 | asm volatile (" \ |
1305 | r1 = 0; \ |
1306 | *(u64*)(r10 - 8) = r1; \ |
1307 | r2 = r10; \ |
1308 | r2 += -8; \ |
1309 | r1 = %[map_array_48b] ll; \ |
1310 | call %[bpf_map_lookup_elem]; \ |
1311 | if r0 == 0 goto l0_%=; \ |
1312 | r1 = *(u8*)(r0 + 0); \ |
1313 | r1 &= 0xf; \ |
1314 | r1 |= 0x7; \ |
1315 | r0 += r1; \ |
1316 | r1 = *(u8*)(r0 + 0); \ |
1317 | r1 &= 0x7; \ |
1318 | r0 -= r1; \ |
1319 | r1 = *(u8*)(r0 + 0); \ |
1320 | l0_%=: r0 = 1; \ |
1321 | exit; \ |
1322 | " : |
1323 | : __imm(bpf_map_lookup_elem), |
1324 | __imm_addr(map_array_48b) |
1325 | : __clobber_all); |
1326 | } |
1327 | |
1328 | SEC("socket" ) |
1329 | __description("map access: value_ptr -= value_ptr" ) |
1330 | __failure __msg("R0 invalid mem access 'scalar'" ) |
1331 | __msg_unpriv("R0 pointer -= pointer prohibited" ) |
1332 | __naked void access_value_ptr_value_ptr_2(void) |
1333 | { |
1334 | asm volatile (" \ |
1335 | r1 = 0; \ |
1336 | *(u64*)(r10 - 8) = r1; \ |
1337 | r2 = r10; \ |
1338 | r2 += -8; \ |
1339 | r1 = %[map_array_48b] ll; \ |
1340 | call %[bpf_map_lookup_elem]; \ |
1341 | if r0 == 0 goto l0_%=; \ |
1342 | r0 -= r0; \ |
1343 | r1 = *(u8*)(r0 + 0); \ |
1344 | l0_%=: r0 = 1; \ |
1345 | exit; \ |
1346 | " : |
1347 | : __imm(bpf_map_lookup_elem), |
1348 | __imm_addr(map_array_48b) |
1349 | : __clobber_all); |
1350 | } |
1351 | |
1352 | SEC("socket" ) |
1353 | __description("map access: trying to leak tainted dst reg" ) |
1354 | __failure __msg("math between map_value pointer and 4294967295 is not allowed" ) |
1355 | __failure_unpriv |
1356 | __naked void to_leak_tainted_dst_reg(void) |
1357 | { |
1358 | asm volatile (" \ |
1359 | r0 = 0; \ |
1360 | r1 = 0; \ |
1361 | *(u64*)(r10 - 8) = r1; \ |
1362 | r2 = r10; \ |
1363 | r2 += -8; \ |
1364 | r1 = %[map_array_48b] ll; \ |
1365 | call %[bpf_map_lookup_elem]; \ |
1366 | if r0 != 0 goto l0_%=; \ |
1367 | exit; \ |
1368 | l0_%=: r2 = r0; \ |
1369 | w1 = 0xFFFFFFFF; \ |
1370 | w1 = w1; \ |
1371 | r2 -= r1; \ |
1372 | *(u64*)(r0 + 0) = r2; \ |
1373 | r0 = 0; \ |
1374 | exit; \ |
1375 | " : |
1376 | : __imm(bpf_map_lookup_elem), |
1377 | __imm_addr(map_array_48b) |
1378 | : __clobber_all); |
1379 | } |
1380 | |
1381 | SEC("tc" ) |
1382 | __description("32bit pkt_ptr -= scalar" ) |
1383 | __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) |
1384 | __naked void _32bit_pkt_ptr_scalar(void) |
1385 | { |
1386 | asm volatile (" \ |
1387 | r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \ |
1388 | r7 = *(u32*)(r1 + %[__sk_buff_data]); \ |
1389 | r6 = r7; \ |
1390 | r6 += 40; \ |
1391 | if r6 > r8 goto l0_%=; \ |
1392 | w4 = w7; \ |
1393 | w6 -= w4; \ |
1394 | l0_%=: r0 = 0; \ |
1395 | exit; \ |
1396 | " : |
1397 | : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), |
1398 | __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) |
1399 | : __clobber_all); |
1400 | } |
1401 | |
1402 | SEC("tc" ) |
1403 | __description("32bit scalar -= pkt_ptr" ) |
1404 | __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) |
1405 | __naked void _32bit_scalar_pkt_ptr(void) |
1406 | { |
1407 | asm volatile (" \ |
1408 | r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \ |
1409 | r7 = *(u32*)(r1 + %[__sk_buff_data]); \ |
1410 | r6 = r7; \ |
1411 | r6 += 40; \ |
1412 | if r6 > r8 goto l0_%=; \ |
1413 | w4 = w6; \ |
1414 | w4 -= w7; \ |
1415 | l0_%=: r0 = 0; \ |
1416 | exit; \ |
1417 | " : |
1418 | : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), |
1419 | __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) |
1420 | : __clobber_all); |
1421 | } |
1422 | |
1423 | char _license[] SEC("license" ) = "GPL" ; |
1424 | |