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