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)
value_ptr_unknown_vs_const(void)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)
value_ptr_const_vs_unknown(void)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)
ptr_const_vs_const_ne(void)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)
ptr_const_vs_const_eq(void)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)
ptr_unknown_vs_unknown_eq(void)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)
ptr_unknown_vs_unknown_lt(void)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)
ptr_unknown_vs_unknown_gt(void)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)
value_ptr_from_different_maps(void)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)
known_scalar_from_different_maps(void)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)
maps_but_same_value_properties(void)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)
value_pointer_and_scalar_1(void)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)
value_pointer_and_scalar_2(void)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)
alu_with_different_scalars_1(void)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)
alu_with_different_scalars_2(void)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)
alu_with_different_scalars_3(void)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)
upper_oob_arith_test_1(void)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)
upper_oob_arith_test_2(void)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)
upper_oob_arith_test_3(void)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")
lower_oob_arith_test_1(void)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)
lower_oob_arith_test_2(void)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)
lower_oob_arith_test_3(void)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)
access_known_scalar_value_ptr_1(void)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)
value_ptr_known_scalar_1(void)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
value_ptr_known_scalar_2_1(void)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
value_ptr_known_scalar_3(void)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)
value_ptr_known_scalar_4(void)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)
value_ptr_known_scalar_5(void)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)
value_ptr_known_scalar_6(void)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)
value_ptr_n_known_scalar(void)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)
unknown_scalar_value_ptr_1(void)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")
__flag(BPF_F_ANY_ALIGNMENT)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")
__flag(BPF_F_ANY_ALIGNMENT)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")
__flag(BPF_F_ANY_ALIGNMENT)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)
value_ptr_unknown_scalar_1(void)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")
__flag(BPF_F_ANY_ALIGNMENT)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)
value_ptr_unknown_scalar_3(void)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
access_value_ptr_value_ptr_1(void)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
access_known_scalar_value_ptr_2(void)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
access_value_ptr_known_scalar(void)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)
value_ptr_known_scalar_2_2(void)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
access_unknown_scalar_value_ptr(void)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
access_value_ptr_unknown_scalar(void)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)
value_ptr_unknown_scalar_2_2(void)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")
access_value_ptr_value_ptr_2(void)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
to_leak_tainted_dst_reg(void)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")
__flag(BPF_F_ANY_ALIGNMENT)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")
__flag(BPF_F_ANY_ALIGNMENT)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