1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/helper_access_var_len.c */
5 #include <bpf/bpf_helpers.h>
16 __uint(type, BPF_MAP_TYPE_HASH);
17 __uint(max_entries, 1);
18 __type(key, long long);
19 __type(value, struct test_val);
20 } map_hash_48b SEC(".maps");
23 __uint(type, BPF_MAP_TYPE_HASH);
24 __uint(max_entries, 1);
25 __type(key, long long);
26 __type(value, long long);
27 } map_hash_8b SEC(".maps");
30 __uint(type, BPF_MAP_TYPE_RINGBUF);
31 __uint(max_entries, 4096);
32 } map_ringbuf SEC(".maps");
35 __description("helper access to variable memory: stack, bitwise AND + JMP, correct bounds")
37 __naked void bitwise_and_jmp_correct_bounds(void)
43 *(u64*)(r10 - 64) = r0; \
44 *(u64*)(r10 - 56) = r0; \
45 *(u64*)(r10 - 48) = r0; \
46 *(u64*)(r10 - 40) = r0; \
47 *(u64*)(r10 - 32) = r0; \
48 *(u64*)(r10 - 24) = r0; \
49 *(u64*)(r10 - 16) = r0; \
50 *(u64*)(r10 - 8) = r0; \
52 *(u64*)(r1 - 128) = r2; \
53 r2 = *(u64*)(r1 - 128); \
56 if r4 >= r2 goto l0_%=; \
58 call %[bpf_probe_read_kernel]; \
62 : __imm(bpf_probe_read_kernel)
67 __description("helper access to variable memory: stack, bitwise AND, zero included")
68 /* in privileged mode reads from uninitialized stack locations are permitted */
69 __success __failure_unpriv
70 __msg_unpriv("invalid indirect read from stack R2 off -64+0 size 64")
72 __naked void stack_bitwise_and_zero_included(void)
75 /* set max stack size */ \
77 *(u64*)(r10 - 128) = r6; \
78 /* set r3 to a random value */ \
79 call %[bpf_get_prandom_u32]; \
81 /* use bitwise AND to limit r3 range to [0, 64] */\
83 r1 = %[map_ringbuf] ll; \
87 /* Call bpf_ringbuf_output(), it is one of a few helper functions with\
88 * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.\
89 * For unpriv this should signal an error, because memory at &fp[-64] is\
92 call %[bpf_ringbuf_output]; \
95 : __imm(bpf_get_prandom_u32),
96 __imm(bpf_ringbuf_output),
97 __imm_addr(map_ringbuf)
102 __description("helper access to variable memory: stack, bitwise AND + JMP, wrong max")
103 __failure __msg("invalid indirect access to stack R1 off=-64 size=65")
104 __naked void bitwise_and_jmp_wrong_max(void)
107 r2 = *(u64*)(r1 + 8); \
110 *(u64*)(r1 - 128) = r2; \
111 r2 = *(u64*)(r1 - 128); \
114 if r4 >= r2 goto l0_%=; \
116 call %[bpf_probe_read_kernel]; \
120 : __imm(bpf_probe_read_kernel)
125 __description("helper access to variable memory: stack, JMP, correct bounds")
127 __naked void memory_stack_jmp_correct_bounds(void)
133 *(u64*)(r10 - 64) = r0; \
134 *(u64*)(r10 - 56) = r0; \
135 *(u64*)(r10 - 48) = r0; \
136 *(u64*)(r10 - 40) = r0; \
137 *(u64*)(r10 - 32) = r0; \
138 *(u64*)(r10 - 24) = r0; \
139 *(u64*)(r10 - 16) = r0; \
140 *(u64*)(r10 - 8) = r0; \
142 *(u64*)(r1 - 128) = r2; \
143 r2 = *(u64*)(r1 - 128); \
144 if r2 > 64 goto l0_%=; \
146 if r4 >= r2 goto l0_%=; \
148 call %[bpf_probe_read_kernel]; \
152 : __imm(bpf_probe_read_kernel)
157 __description("helper access to variable memory: stack, JMP (signed), correct bounds")
159 __naked void stack_jmp_signed_correct_bounds(void)
165 *(u64*)(r10 - 64) = r0; \
166 *(u64*)(r10 - 56) = r0; \
167 *(u64*)(r10 - 48) = r0; \
168 *(u64*)(r10 - 40) = r0; \
169 *(u64*)(r10 - 32) = r0; \
170 *(u64*)(r10 - 24) = r0; \
171 *(u64*)(r10 - 16) = r0; \
172 *(u64*)(r10 - 8) = r0; \
174 *(u64*)(r1 - 128) = r2; \
175 r2 = *(u64*)(r1 - 128); \
176 if r2 s> 64 goto l0_%=; \
178 if r4 s>= r2 goto l0_%=; \
180 call %[bpf_probe_read_kernel]; \
184 : __imm(bpf_probe_read_kernel)
189 __description("helper access to variable memory: stack, JMP, bounds + offset")
190 __failure __msg("invalid indirect access to stack R1 off=-64 size=65")
191 __naked void memory_stack_jmp_bounds_offset(void)
194 r2 = *(u64*)(r1 + 8); \
197 *(u64*)(r1 - 128) = r2; \
198 r2 = *(u64*)(r1 - 128); \
199 if r2 > 64 goto l0_%=; \
201 if r4 >= r2 goto l0_%=; \
204 call %[bpf_probe_read_kernel]; \
208 : __imm(bpf_probe_read_kernel)
213 __description("helper access to variable memory: stack, JMP, wrong max")
214 __failure __msg("invalid indirect access to stack R1 off=-64 size=65")
215 __naked void memory_stack_jmp_wrong_max(void)
218 r2 = *(u64*)(r1 + 8); \
221 *(u64*)(r1 - 128) = r2; \
222 r2 = *(u64*)(r1 - 128); \
223 if r2 > 65 goto l0_%=; \
225 if r4 >= r2 goto l0_%=; \
227 call %[bpf_probe_read_kernel]; \
231 : __imm(bpf_probe_read_kernel)
236 __description("helper access to variable memory: stack, JMP, no max check")
238 /* because max wasn't checked, signed min is negative */
239 __msg("R2 min value is negative, either use unsigned or 'var &= const'")
240 __naked void stack_jmp_no_max_check(void)
243 r2 = *(u64*)(r1 + 8); \
246 *(u64*)(r1 - 128) = r2; \
247 r2 = *(u64*)(r1 - 128); \
249 if r4 >= r2 goto l0_%=; \
251 call %[bpf_probe_read_kernel]; \
255 : __imm(bpf_probe_read_kernel)
260 __description("helper access to variable memory: stack, JMP, no min check")
261 /* in privileged mode reads from uninitialized stack locations are permitted */
262 __success __failure_unpriv
263 __msg_unpriv("invalid indirect read from stack R2 off -64+0 size 64")
265 __naked void stack_jmp_no_min_check(void)
268 /* set max stack size */ \
270 *(u64*)(r10 - 128) = r6; \
271 /* set r3 to a random value */ \
272 call %[bpf_get_prandom_u32]; \
274 /* use JMP to limit r3 range to [0, 64] */ \
275 if r3 > 64 goto l0_%=; \
276 r1 = %[map_ringbuf] ll; \
280 /* Call bpf_ringbuf_output(), it is one of a few helper functions with\
281 * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.\
282 * For unpriv this should signal an error, because memory at &fp[-64] is\
285 call %[bpf_ringbuf_output]; \
289 : __imm(bpf_get_prandom_u32),
290 __imm(bpf_ringbuf_output),
291 __imm_addr(map_ringbuf)
296 __description("helper access to variable memory: stack, JMP (signed), no min check")
297 __failure __msg("R2 min value is negative")
298 __naked void jmp_signed_no_min_check(void)
301 r2 = *(u64*)(r1 + 8); \
304 *(u64*)(r1 - 128) = r2; \
305 r2 = *(u64*)(r1 - 128); \
306 if r2 s> 64 goto l0_%=; \
308 call %[bpf_probe_read_kernel]; \
312 : __imm(bpf_probe_read_kernel)
317 __description("helper access to variable memory: map, JMP, correct bounds")
319 __naked void memory_map_jmp_correct_bounds(void)
325 *(u64*)(r2 + 0) = r1; \
326 r1 = %[map_hash_48b] ll; \
327 call %[bpf_map_lookup_elem]; \
328 if r0 == 0 goto l0_%=; \
330 r2 = %[sizeof_test_val]; \
331 *(u64*)(r10 - 128) = r2; \
332 r2 = *(u64*)(r10 - 128); \
333 if r2 s> %[sizeof_test_val] goto l1_%=; \
335 if r4 s>= r2 goto l1_%=; \
337 call %[bpf_probe_read_kernel]; \
341 : __imm(bpf_map_lookup_elem),
342 __imm(bpf_probe_read_kernel),
343 __imm_addr(map_hash_48b),
344 __imm_const(sizeof_test_val, sizeof(struct test_val))
349 __description("helper access to variable memory: map, JMP, wrong max")
350 __failure __msg("invalid access to map value, value_size=48 off=0 size=49")
351 __naked void memory_map_jmp_wrong_max(void)
354 r6 = *(u64*)(r1 + 8); \
358 *(u64*)(r2 + 0) = r1; \
359 r1 = %[map_hash_48b] ll; \
360 call %[bpf_map_lookup_elem]; \
361 if r0 == 0 goto l0_%=; \
364 *(u64*)(r10 - 128) = r2; \
365 r2 = *(u64*)(r10 - 128); \
366 if r2 s> %[__imm_0] goto l1_%=; \
368 if r4 s>= r2 goto l1_%=; \
370 call %[bpf_probe_read_kernel]; \
374 : __imm(bpf_map_lookup_elem),
375 __imm(bpf_probe_read_kernel),
376 __imm_addr(map_hash_48b),
377 __imm_const(__imm_0, sizeof(struct test_val) + 1)
382 __description("helper access to variable memory: map adjusted, JMP, correct bounds")
384 __naked void map_adjusted_jmp_correct_bounds(void)
390 *(u64*)(r2 + 0) = r1; \
391 r1 = %[map_hash_48b] ll; \
392 call %[bpf_map_lookup_elem]; \
393 if r0 == 0 goto l0_%=; \
396 r2 = %[sizeof_test_val]; \
397 *(u64*)(r10 - 128) = r2; \
398 r2 = *(u64*)(r10 - 128); \
399 if r2 s> %[__imm_0] goto l1_%=; \
401 if r4 s>= r2 goto l1_%=; \
403 call %[bpf_probe_read_kernel]; \
407 : __imm(bpf_map_lookup_elem),
408 __imm(bpf_probe_read_kernel),
409 __imm_addr(map_hash_48b),
410 __imm_const(__imm_0, sizeof(struct test_val) - 20),
411 __imm_const(sizeof_test_val, sizeof(struct test_val))
416 __description("helper access to variable memory: map adjusted, JMP, wrong max")
417 __failure __msg("R1 min value is outside of the allowed memory range")
418 __naked void map_adjusted_jmp_wrong_max(void)
421 r6 = *(u64*)(r1 + 8); \
425 *(u64*)(r2 + 0) = r1; \
426 r1 = %[map_hash_48b] ll; \
427 call %[bpf_map_lookup_elem]; \
428 if r0 == 0 goto l0_%=; \
432 *(u64*)(r10 - 128) = r2; \
433 r2 = *(u64*)(r10 - 128); \
434 if r2 s> %[__imm_0] goto l1_%=; \
436 if r4 s>= r2 goto l1_%=; \
438 call %[bpf_probe_read_kernel]; \
442 : __imm(bpf_map_lookup_elem),
443 __imm(bpf_probe_read_kernel),
444 __imm_addr(map_hash_48b),
445 __imm_const(__imm_0, sizeof(struct test_val) - 19)
450 __description("helper access to variable memory: size = 0 allowed on NULL (ARG_PTR_TO_MEM_OR_NULL)")
451 __success __retval(0)
452 __naked void ptr_to_mem_or_null_1(void)
460 call %[bpf_csum_diff]; \
463 : __imm(bpf_csum_diff)
468 __description("helper access to variable memory: size > 0 not allowed on NULL (ARG_PTR_TO_MEM_OR_NULL)")
469 __failure __msg("R1 type=scalar expected=fp")
470 __naked void ptr_to_mem_or_null_2(void)
473 r2 = *(u32*)(r1 + 0); \
475 *(u64*)(r10 - 128) = r2; \
476 r2 = *(u64*)(r10 - 128); \
481 call %[bpf_csum_diff]; \
484 : __imm(bpf_csum_diff)
489 __description("helper access to variable memory: size = 0 allowed on != NULL stack pointer (ARG_PTR_TO_MEM_OR_NULL)")
490 __success __retval(0)
491 __naked void ptr_to_mem_or_null_3(void)
497 *(u64*)(r1 + 0) = r2; \
502 call %[bpf_csum_diff]; \
505 : __imm(bpf_csum_diff)
510 __description("helper access to variable memory: size = 0 allowed on != NULL map pointer (ARG_PTR_TO_MEM_OR_NULL)")
511 __success __retval(0)
512 __naked void ptr_to_mem_or_null_4(void)
516 *(u64*)(r10 - 8) = r1; \
519 r1 = %[map_hash_8b] ll; \
520 call %[bpf_map_lookup_elem]; \
521 if r0 == 0 goto l0_%=; \
527 call %[bpf_csum_diff]; \
530 : __imm(bpf_csum_diff),
531 __imm(bpf_map_lookup_elem),
532 __imm_addr(map_hash_8b)
537 __description("helper access to variable memory: size possible = 0 allowed on != NULL stack pointer (ARG_PTR_TO_MEM_OR_NULL)")
538 __success __retval(0)
539 __naked void ptr_to_mem_or_null_5(void)
543 *(u64*)(r10 - 8) = r1; \
546 r1 = %[map_hash_8b] ll; \
547 call %[bpf_map_lookup_elem]; \
548 if r0 == 0 goto l0_%=; \
549 r2 = *(u64*)(r0 + 0); \
550 if r2 > 8 goto l0_%=; \
553 *(u64*)(r1 + 0) = r2; \
557 call %[bpf_csum_diff]; \
560 : __imm(bpf_csum_diff),
561 __imm(bpf_map_lookup_elem),
562 __imm_addr(map_hash_8b)
567 __description("helper access to variable memory: size possible = 0 allowed on != NULL map pointer (ARG_PTR_TO_MEM_OR_NULL)")
568 __success __retval(0)
569 __naked void ptr_to_mem_or_null_6(void)
573 *(u64*)(r10 - 8) = r1; \
576 r1 = %[map_hash_8b] ll; \
577 call %[bpf_map_lookup_elem]; \
578 if r0 == 0 goto l0_%=; \
580 r2 = *(u64*)(r0 + 0); \
581 if r2 > 8 goto l0_%=; \
585 call %[bpf_csum_diff]; \
588 : __imm(bpf_csum_diff),
589 __imm(bpf_map_lookup_elem),
590 __imm_addr(map_hash_8b)
595 __description("helper access to variable memory: size possible = 0 allowed on != NULL packet pointer (ARG_PTR_TO_MEM_OR_NULL)")
596 __success __retval(0)
597 /* csum_diff of 64-byte packet */
598 __flag(BPF_F_ANY_ALIGNMENT)
599 __naked void ptr_to_mem_or_null_7(void)
602 r6 = *(u32*)(r1 + %[__sk_buff_data]); \
603 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \
606 if r0 > r3 goto l0_%=; \
608 r2 = *(u64*)(r6 + 0); \
609 if r2 > 8 goto l0_%=; \
613 call %[bpf_csum_diff]; \
616 : __imm(bpf_csum_diff),
617 __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
618 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
623 __description("helper access to variable memory: size = 0 not allowed on NULL (!ARG_PTR_TO_MEM_OR_NULL)")
624 __failure __msg("R1 type=scalar expected=fp")
625 __naked void ptr_to_mem_or_null_8(void)
631 call %[bpf_probe_read_kernel]; \
634 : __imm(bpf_probe_read_kernel)
639 __description("helper access to variable memory: size > 0 not allowed on NULL (!ARG_PTR_TO_MEM_OR_NULL)")
640 __failure __msg("R1 type=scalar expected=fp")
641 __naked void ptr_to_mem_or_null_9(void)
647 call %[bpf_probe_read_kernel]; \
650 : __imm(bpf_probe_read_kernel)
655 __description("helper access to variable memory: size = 0 allowed on != NULL stack pointer (!ARG_PTR_TO_MEM_OR_NULL)")
657 __naked void ptr_to_mem_or_null_10(void)
664 call %[bpf_probe_read_kernel]; \
667 : __imm(bpf_probe_read_kernel)
672 __description("helper access to variable memory: size = 0 allowed on != NULL map pointer (!ARG_PTR_TO_MEM_OR_NULL)")
674 __naked void ptr_to_mem_or_null_11(void)
678 *(u64*)(r10 - 8) = r1; \
681 r1 = %[map_hash_8b] ll; \
682 call %[bpf_map_lookup_elem]; \
683 if r0 == 0 goto l0_%=; \
687 call %[bpf_probe_read_kernel]; \
690 : __imm(bpf_map_lookup_elem),
691 __imm(bpf_probe_read_kernel),
692 __imm_addr(map_hash_8b)
697 __description("helper access to variable memory: size possible = 0 allowed on != NULL stack pointer (!ARG_PTR_TO_MEM_OR_NULL)")
699 __naked void ptr_to_mem_or_null_12(void)
703 *(u64*)(r10 - 8) = r1; \
706 r1 = %[map_hash_8b] ll; \
707 call %[bpf_map_lookup_elem]; \
708 if r0 == 0 goto l0_%=; \
709 r2 = *(u64*)(r0 + 0); \
710 if r2 > 8 goto l0_%=; \
714 call %[bpf_probe_read_kernel]; \
717 : __imm(bpf_map_lookup_elem),
718 __imm(bpf_probe_read_kernel),
719 __imm_addr(map_hash_8b)
724 __description("helper access to variable memory: size possible = 0 allowed on != NULL map pointer (!ARG_PTR_TO_MEM_OR_NULL)")
726 __naked void ptr_to_mem_or_null_13(void)
730 *(u64*)(r10 - 8) = r1; \
733 r1 = %[map_hash_8b] ll; \
734 call %[bpf_map_lookup_elem]; \
735 if r0 == 0 goto l0_%=; \
737 r2 = *(u64*)(r0 + 0); \
738 if r2 > 8 goto l0_%=; \
740 call %[bpf_probe_read_kernel]; \
743 : __imm(bpf_map_lookup_elem),
744 __imm(bpf_probe_read_kernel),
745 __imm_addr(map_hash_8b)
750 __description("helper access to variable memory: 8 bytes leak")
751 /* in privileged mode reads from uninitialized stack locations are permitted */
752 __success __failure_unpriv
753 __msg_unpriv("invalid indirect read from stack R2 off -64+32 size 64")
755 __naked void variable_memory_8_bytes_leak(void)
758 /* set max stack size */ \
760 *(u64*)(r10 - 128) = r6; \
761 /* set r3 to a random value */ \
762 call %[bpf_get_prandom_u32]; \
764 r1 = %[map_ringbuf] ll; \
768 *(u64*)(r10 - 64) = r0; \
769 *(u64*)(r10 - 56) = r0; \
770 *(u64*)(r10 - 48) = r0; \
771 *(u64*)(r10 - 40) = r0; \
772 /* Note: fp[-32] left uninitialized */ \
773 *(u64*)(r10 - 24) = r0; \
774 *(u64*)(r10 - 16) = r0; \
775 *(u64*)(r10 - 8) = r0; \
776 /* Limit r3 range to [1, 64] */ \
780 /* Call bpf_ringbuf_output(), it is one of a few helper functions with\
781 * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.\
782 * For unpriv this should signal an error, because memory region [1, 64]\
783 * at &fp[-64] is not fully initialized. \
785 call %[bpf_ringbuf_output]; \
789 : __imm(bpf_get_prandom_u32),
790 __imm(bpf_ringbuf_output),
791 __imm_addr(map_ringbuf)
796 __description("helper access to variable memory: 8 bytes no leak (init memory)")
798 __naked void bytes_no_leak_init_memory(void)
804 *(u64*)(r10 - 64) = r0; \
805 *(u64*)(r10 - 56) = r0; \
806 *(u64*)(r10 - 48) = r0; \
807 *(u64*)(r10 - 40) = r0; \
808 *(u64*)(r10 - 32) = r0; \
809 *(u64*)(r10 - 24) = r0; \
810 *(u64*)(r10 - 16) = r0; \
811 *(u64*)(r10 - 8) = r0; \
817 call %[bpf_probe_read_kernel]; \
818 r1 = *(u64*)(r10 - 16); \
821 : __imm(bpf_probe_read_kernel)
825 char _license[] SEC("license") = "GPL";