1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Facebook */
3 
4 #include <errno.h>
5 #include <string.h>
6 #include <linux/bpf.h>
7 #include <bpf/bpf_helpers.h>
8 #include "bpf_misc.h"
9 
10 char _license[] SEC("license") = "GPL";
11 
12 struct test_info {
13 	int x;
14 	struct bpf_dynptr ptr;
15 };
16 
17 struct {
18 	__uint(type, BPF_MAP_TYPE_ARRAY);
19 	__uint(max_entries, 1);
20 	__type(key, __u32);
21 	__type(value, struct bpf_dynptr);
22 } array_map1 SEC(".maps");
23 
24 struct {
25 	__uint(type, BPF_MAP_TYPE_ARRAY);
26 	__uint(max_entries, 1);
27 	__type(key, __u32);
28 	__type(value, struct test_info);
29 } array_map2 SEC(".maps");
30 
31 struct {
32 	__uint(type, BPF_MAP_TYPE_ARRAY);
33 	__uint(max_entries, 1);
34 	__type(key, __u32);
35 	__type(value, __u32);
36 } array_map3 SEC(".maps");
37 
38 struct {
39 	__uint(type, BPF_MAP_TYPE_ARRAY);
40 	__uint(max_entries, 1);
41 	__type(key, __u32);
42 	__type(value, __u64);
43 } array_map4 SEC(".maps");
44 
45 struct sample {
46 	int pid;
47 	long value;
48 	char comm[16];
49 };
50 
51 struct {
52 	__uint(type, BPF_MAP_TYPE_RINGBUF);
53 	__uint(max_entries, 4096);
54 } ringbuf SEC(".maps");
55 
56 int err, val;
57 
58 static int get_map_val_dynptr(struct bpf_dynptr *ptr)
59 {
60 	__u32 key = 0, *map_val;
61 
62 	bpf_map_update_elem(&array_map3, &key, &val, 0);
63 
64 	map_val = bpf_map_lookup_elem(&array_map3, &key);
65 	if (!map_val)
66 		return -ENOENT;
67 
68 	bpf_dynptr_from_mem(map_val, sizeof(*map_val), 0, ptr);
69 
70 	return 0;
71 }
72 
73 /* Every bpf_ringbuf_reserve_dynptr call must have a corresponding
74  * bpf_ringbuf_submit/discard_dynptr call
75  */
76 SEC("?raw_tp")
77 __failure __msg("Unreleased reference id=2")
78 int ringbuf_missing_release1(void *ctx)
79 {
80 	struct bpf_dynptr ptr;
81 
82 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
83 
84 	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
85 
86 	return 0;
87 }
88 
89 SEC("?raw_tp")
90 __failure __msg("Unreleased reference id=4")
91 int ringbuf_missing_release2(void *ctx)
92 {
93 	struct bpf_dynptr ptr1, ptr2;
94 	struct sample *sample;
95 
96 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr1);
97 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
98 
99 	sample = bpf_dynptr_data(&ptr1, 0, sizeof(*sample));
100 	if (!sample) {
101 		bpf_ringbuf_discard_dynptr(&ptr1, 0);
102 		bpf_ringbuf_discard_dynptr(&ptr2, 0);
103 		return 0;
104 	}
105 
106 	bpf_ringbuf_submit_dynptr(&ptr1, 0);
107 
108 	/* missing a call to bpf_ringbuf_discard/submit_dynptr on ptr2 */
109 
110 	return 0;
111 }
112 
113 static int missing_release_callback_fn(__u32 index, void *data)
114 {
115 	struct bpf_dynptr ptr;
116 
117 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
118 
119 	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
120 
121 	return 0;
122 }
123 
124 /* Any dynptr initialized within a callback must have bpf_dynptr_put called */
125 SEC("?raw_tp")
126 __failure __msg("Unreleased reference id")
127 int ringbuf_missing_release_callback(void *ctx)
128 {
129 	bpf_loop(10, missing_release_callback_fn, NULL, 0);
130 	return 0;
131 }
132 
133 /* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */
134 SEC("?raw_tp")
135 __failure __msg("arg 1 is an unacquired reference")
136 int ringbuf_release_uninit_dynptr(void *ctx)
137 {
138 	struct bpf_dynptr ptr;
139 
140 	/* this should fail */
141 	bpf_ringbuf_submit_dynptr(&ptr, 0);
142 
143 	return 0;
144 }
145 
146 /* A dynptr can't be used after it has been invalidated */
147 SEC("?raw_tp")
148 __failure __msg("Expected an initialized dynptr as arg #3")
149 int use_after_invalid(void *ctx)
150 {
151 	struct bpf_dynptr ptr;
152 	char read_data[64];
153 
154 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr);
155 
156 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
157 
158 	bpf_ringbuf_submit_dynptr(&ptr, 0);
159 
160 	/* this should fail */
161 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
162 
163 	return 0;
164 }
165 
166 /* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */
167 SEC("?raw_tp")
168 __failure __msg("type=mem expected=ringbuf_mem")
169 int ringbuf_invalid_api(void *ctx)
170 {
171 	struct bpf_dynptr ptr;
172 	struct sample *sample;
173 
174 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
175 	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
176 	if (!sample)
177 		goto done;
178 
179 	sample->pid = 123;
180 
181 	/* invalid API use. need to use dynptr API to submit/discard */
182 	bpf_ringbuf_submit(sample, 0);
183 
184 done:
185 	bpf_ringbuf_discard_dynptr(&ptr, 0);
186 	return 0;
187 }
188 
189 /* Can't add a dynptr to a map */
190 SEC("?raw_tp")
191 __failure __msg("invalid indirect read from stack")
192 int add_dynptr_to_map1(void *ctx)
193 {
194 	struct bpf_dynptr ptr;
195 	int key = 0;
196 
197 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
198 
199 	/* this should fail */
200 	bpf_map_update_elem(&array_map1, &key, &ptr, 0);
201 
202 	bpf_ringbuf_submit_dynptr(&ptr, 0);
203 
204 	return 0;
205 }
206 
207 /* Can't add a struct with an embedded dynptr to a map */
208 SEC("?raw_tp")
209 __failure __msg("invalid indirect read from stack")
210 int add_dynptr_to_map2(void *ctx)
211 {
212 	struct test_info x;
213 	int key = 0;
214 
215 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &x.ptr);
216 
217 	/* this should fail */
218 	bpf_map_update_elem(&array_map2, &key, &x, 0);
219 
220 	bpf_ringbuf_submit_dynptr(&x.ptr, 0);
221 
222 	return 0;
223 }
224 
225 /* A data slice can't be accessed out of bounds */
226 SEC("?raw_tp")
227 __failure __msg("value is outside of the allowed memory range")
228 int data_slice_out_of_bounds_ringbuf(void *ctx)
229 {
230 	struct bpf_dynptr ptr;
231 	void *data;
232 
233 	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
234 
235 	data  = bpf_dynptr_data(&ptr, 0, 8);
236 	if (!data)
237 		goto done;
238 
239 	/* can't index out of bounds of the data slice */
240 	val = *((char *)data + 8);
241 
242 done:
243 	bpf_ringbuf_submit_dynptr(&ptr, 0);
244 	return 0;
245 }
246 
247 SEC("?raw_tp")
248 __failure __msg("value is outside of the allowed memory range")
249 int data_slice_out_of_bounds_map_value(void *ctx)
250 {
251 	__u32 key = 0, map_val;
252 	struct bpf_dynptr ptr;
253 	void *data;
254 
255 	get_map_val_dynptr(&ptr);
256 
257 	data  = bpf_dynptr_data(&ptr, 0, sizeof(map_val));
258 	if (!data)
259 		return 0;
260 
261 	/* can't index out of bounds of the data slice */
262 	val = *((char *)data + (sizeof(map_val) + 1));
263 
264 	return 0;
265 }
266 
267 /* A data slice can't be used after it has been released */
268 SEC("?raw_tp")
269 __failure __msg("invalid mem access 'scalar'")
270 int data_slice_use_after_release1(void *ctx)
271 {
272 	struct bpf_dynptr ptr;
273 	struct sample *sample;
274 
275 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
276 	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
277 	if (!sample)
278 		goto done;
279 
280 	sample->pid = 123;
281 
282 	bpf_ringbuf_submit_dynptr(&ptr, 0);
283 
284 	/* this should fail */
285 	val = sample->pid;
286 
287 	return 0;
288 
289 done:
290 	bpf_ringbuf_discard_dynptr(&ptr, 0);
291 	return 0;
292 }
293 
294 /* A data slice can't be used after it has been released.
295  *
296  * This tests the case where the data slice tracks a dynptr (ptr2)
297  * that is at a non-zero offset from the frame pointer (ptr1 is at fp,
298  * ptr2 is at fp - 16).
299  */
300 SEC("?raw_tp")
301 __failure __msg("invalid mem access 'scalar'")
302 int data_slice_use_after_release2(void *ctx)
303 {
304 	struct bpf_dynptr ptr1, ptr2;
305 	struct sample *sample;
306 
307 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1);
308 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
309 
310 	sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample));
311 	if (!sample)
312 		goto done;
313 
314 	sample->pid = 23;
315 
316 	bpf_ringbuf_submit_dynptr(&ptr2, 0);
317 
318 	/* this should fail */
319 	sample->pid = 23;
320 
321 	bpf_ringbuf_submit_dynptr(&ptr1, 0);
322 
323 	return 0;
324 
325 done:
326 	bpf_ringbuf_discard_dynptr(&ptr2, 0);
327 	bpf_ringbuf_discard_dynptr(&ptr1, 0);
328 	return 0;
329 }
330 
331 /* A data slice must be first checked for NULL */
332 SEC("?raw_tp")
333 __failure __msg("invalid mem access 'mem_or_null'")
334 int data_slice_missing_null_check1(void *ctx)
335 {
336 	struct bpf_dynptr ptr;
337 	void *data;
338 
339 	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
340 
341 	data  = bpf_dynptr_data(&ptr, 0, 8);
342 
343 	/* missing if (!data) check */
344 
345 	/* this should fail */
346 	*(__u8 *)data = 3;
347 
348 	bpf_ringbuf_submit_dynptr(&ptr, 0);
349 	return 0;
350 }
351 
352 /* A data slice can't be dereferenced if it wasn't checked for null */
353 SEC("?raw_tp")
354 __failure __msg("invalid mem access 'mem_or_null'")
355 int data_slice_missing_null_check2(void *ctx)
356 {
357 	struct bpf_dynptr ptr;
358 	__u64 *data1, *data2;
359 
360 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
361 
362 	data1 = bpf_dynptr_data(&ptr, 0, 8);
363 	data2 = bpf_dynptr_data(&ptr, 0, 8);
364 	if (data1)
365 		/* this should fail */
366 		*data2 = 3;
367 
368 done:
369 	bpf_ringbuf_discard_dynptr(&ptr, 0);
370 	return 0;
371 }
372 
373 /* Can't pass in a dynptr as an arg to a helper function that doesn't take in a
374  * dynptr argument
375  */
376 SEC("?raw_tp")
377 __failure __msg("invalid indirect read from stack")
378 int invalid_helper1(void *ctx)
379 {
380 	struct bpf_dynptr ptr;
381 
382 	get_map_val_dynptr(&ptr);
383 
384 	/* this should fail */
385 	bpf_strncmp((const char *)&ptr, sizeof(ptr), "hello!");
386 
387 	return 0;
388 }
389 
390 /* A dynptr can't be passed into a helper function at a non-zero offset */
391 SEC("?raw_tp")
392 __failure __msg("cannot pass in dynptr at an offset=-8")
393 int invalid_helper2(void *ctx)
394 {
395 	struct bpf_dynptr ptr;
396 	char read_data[64];
397 
398 	get_map_val_dynptr(&ptr);
399 
400 	/* this should fail */
401 	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0);
402 
403 	return 0;
404 }
405 
406 /* A bpf_dynptr is invalidated if it's been written into */
407 SEC("?raw_tp")
408 __failure __msg("Expected an initialized dynptr as arg #1")
409 int invalid_write1(void *ctx)
410 {
411 	struct bpf_dynptr ptr;
412 	void *data;
413 	__u8 x = 0;
414 
415 	get_map_val_dynptr(&ptr);
416 
417 	memcpy(&ptr, &x, sizeof(x));
418 
419 	/* this should fail */
420 	data = bpf_dynptr_data(&ptr, 0, 1);
421 
422 	return 0;
423 }
424 
425 /*
426  * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed
427  * offset
428  */
429 SEC("?raw_tp")
430 __failure __msg("cannot overwrite referenced dynptr")
431 int invalid_write2(void *ctx)
432 {
433 	struct bpf_dynptr ptr;
434 	char read_data[64];
435 	__u8 x = 0;
436 
437 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
438 
439 	memcpy((void *)&ptr + 8, &x, sizeof(x));
440 
441 	/* this should fail */
442 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
443 
444 	bpf_ringbuf_submit_dynptr(&ptr, 0);
445 
446 	return 0;
447 }
448 
449 /*
450  * A bpf_dynptr can't be used as a dynptr if it has been written into at a
451  * non-const offset
452  */
453 SEC("?raw_tp")
454 __failure __msg("cannot overwrite referenced dynptr")
455 int invalid_write3(void *ctx)
456 {
457 	struct bpf_dynptr ptr;
458 	char stack_buf[16];
459 	unsigned long len;
460 	__u8 x = 0;
461 
462 	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
463 
464 	memcpy(stack_buf, &val, sizeof(val));
465 	len = stack_buf[0] & 0xf;
466 
467 	memcpy((void *)&ptr + len, &x, sizeof(x));
468 
469 	/* this should fail */
470 	bpf_ringbuf_submit_dynptr(&ptr, 0);
471 
472 	return 0;
473 }
474 
475 static int invalid_write4_callback(__u32 index, void *data)
476 {
477 	*(__u32 *)data = 123;
478 
479 	return 0;
480 }
481 
482 /* If the dynptr is written into in a callback function, it should
483  * be invalidated as a dynptr
484  */
485 SEC("?raw_tp")
486 __failure __msg("cannot overwrite referenced dynptr")
487 int invalid_write4(void *ctx)
488 {
489 	struct bpf_dynptr ptr;
490 
491 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
492 
493 	bpf_loop(10, invalid_write4_callback, &ptr, 0);
494 
495 	/* this should fail */
496 	bpf_ringbuf_submit_dynptr(&ptr, 0);
497 
498 	return 0;
499 }
500 
501 /* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */
502 struct bpf_dynptr global_dynptr;
503 
504 SEC("?raw_tp")
505 __failure __msg("type=map_value expected=fp")
506 int global(void *ctx)
507 {
508 	/* this should fail */
509 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &global_dynptr);
510 
511 	bpf_ringbuf_discard_dynptr(&global_dynptr, 0);
512 
513 	return 0;
514 }
515 
516 /* A direct read should fail */
517 SEC("?raw_tp")
518 __failure __msg("invalid read from stack")
519 int invalid_read1(void *ctx)
520 {
521 	struct bpf_dynptr ptr;
522 
523 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
524 
525 	/* this should fail */
526 	val = *(int *)&ptr;
527 
528 	bpf_ringbuf_discard_dynptr(&ptr, 0);
529 
530 	return 0;
531 }
532 
533 /* A direct read at an offset should fail */
534 SEC("?raw_tp")
535 __failure __msg("cannot pass in dynptr at an offset")
536 int invalid_read2(void *ctx)
537 {
538 	struct bpf_dynptr ptr;
539 	char read_data[64];
540 
541 	get_map_val_dynptr(&ptr);
542 
543 	/* this should fail */
544 	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0);
545 
546 	return 0;
547 }
548 
549 /* A direct read at an offset into the lower stack slot should fail */
550 SEC("?raw_tp")
551 __failure __msg("invalid read from stack")
552 int invalid_read3(void *ctx)
553 {
554 	struct bpf_dynptr ptr1, ptr2;
555 
556 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr1);
557 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr2);
558 
559 	/* this should fail */
560 	memcpy(&val, (void *)&ptr1 + 8, sizeof(val));
561 
562 	bpf_ringbuf_discard_dynptr(&ptr1, 0);
563 	bpf_ringbuf_discard_dynptr(&ptr2, 0);
564 
565 	return 0;
566 }
567 
568 static int invalid_read4_callback(__u32 index, void *data)
569 {
570 	/* this should fail */
571 	val = *(__u32 *)data;
572 
573 	return 0;
574 }
575 
576 /* A direct read within a callback function should fail */
577 SEC("?raw_tp")
578 __failure __msg("invalid read from stack")
579 int invalid_read4(void *ctx)
580 {
581 	struct bpf_dynptr ptr;
582 
583 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
584 
585 	bpf_loop(10, invalid_read4_callback, &ptr, 0);
586 
587 	bpf_ringbuf_submit_dynptr(&ptr, 0);
588 
589 	return 0;
590 }
591 
592 /* Initializing a dynptr on an offset should fail */
593 SEC("?raw_tp")
594 __failure __msg("cannot pass in dynptr at an offset=0")
595 int invalid_offset(void *ctx)
596 {
597 	struct bpf_dynptr ptr;
598 
599 	/* this should fail */
600 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr + 1);
601 
602 	bpf_ringbuf_discard_dynptr(&ptr, 0);
603 
604 	return 0;
605 }
606 
607 /* Can't release a dynptr twice */
608 SEC("?raw_tp")
609 __failure __msg("arg 1 is an unacquired reference")
610 int release_twice(void *ctx)
611 {
612 	struct bpf_dynptr ptr;
613 
614 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
615 
616 	bpf_ringbuf_discard_dynptr(&ptr, 0);
617 
618 	/* this second release should fail */
619 	bpf_ringbuf_discard_dynptr(&ptr, 0);
620 
621 	return 0;
622 }
623 
624 static int release_twice_callback_fn(__u32 index, void *data)
625 {
626 	/* this should fail */
627 	bpf_ringbuf_discard_dynptr(data, 0);
628 
629 	return 0;
630 }
631 
632 /* Test that releasing a dynptr twice, where one of the releases happens
633  * within a callback function, fails
634  */
635 SEC("?raw_tp")
636 __failure __msg("arg 1 is an unacquired reference")
637 int release_twice_callback(void *ctx)
638 {
639 	struct bpf_dynptr ptr;
640 
641 	bpf_ringbuf_reserve_dynptr(&ringbuf, 32, 0, &ptr);
642 
643 	bpf_ringbuf_discard_dynptr(&ptr, 0);
644 
645 	bpf_loop(10, release_twice_callback_fn, &ptr, 0);
646 
647 	return 0;
648 }
649 
650 /* Reject unsupported local mem types for dynptr_from_mem API */
651 SEC("?raw_tp")
652 __failure __msg("Unsupported reg type fp for bpf_dynptr_from_mem data")
653 int dynptr_from_mem_invalid_api(void *ctx)
654 {
655 	struct bpf_dynptr ptr;
656 	int x = 0;
657 
658 	/* this should fail */
659 	bpf_dynptr_from_mem(&x, sizeof(x), 0, &ptr);
660 
661 	return 0;
662 }
663 
664 SEC("?tc")
665 __failure __msg("cannot overwrite referenced dynptr") __log_level(2)
666 int dynptr_pruning_overwrite(struct __sk_buff *ctx)
667 {
668 	asm volatile (
669 		"r9 = 0xeB9F;				\
670 		 r6 = %[ringbuf] ll;			\
671 		 r1 = r6;				\
672 		 r2 = 8;				\
673 		 r3 = 0;				\
674 		 r4 = r10;				\
675 		 r4 += -16;				\
676 		 call %[bpf_ringbuf_reserve_dynptr];	\
677 		 if r0 == 0 goto pjmp1;			\
678 		 goto pjmp2;				\
679 	pjmp1:						\
680 		 *(u64 *)(r10 - 16) = r9;		\
681 	pjmp2:						\
682 		 r1 = r10;				\
683 		 r1 += -16;				\
684 		 r2 = 0;				\
685 		 call %[bpf_ringbuf_discard_dynptr];	"
686 		:
687 		: __imm(bpf_ringbuf_reserve_dynptr),
688 		  __imm(bpf_ringbuf_discard_dynptr),
689 		  __imm_addr(ringbuf)
690 		: __clobber_all
691 	);
692 	return 0;
693 }
694 
695 SEC("?tc")
696 __success __msg("12: safe") __log_level(2)
697 int dynptr_pruning_stacksafe(struct __sk_buff *ctx)
698 {
699 	asm volatile (
700 		"r9 = 0xeB9F;				\
701 		 r6 = %[ringbuf] ll;			\
702 		 r1 = r6;				\
703 		 r2 = 8;				\
704 		 r3 = 0;				\
705 		 r4 = r10;				\
706 		 r4 += -16;				\
707 		 call %[bpf_ringbuf_reserve_dynptr];	\
708 		 if r0 == 0 goto stjmp1;		\
709 		 goto stjmp2;				\
710 	stjmp1:						\
711 		 r9 = r9;				\
712 	stjmp2:						\
713 		 r1 = r10;				\
714 		 r1 += -16;				\
715 		 r2 = 0;				\
716 		 call %[bpf_ringbuf_discard_dynptr];	"
717 		:
718 		: __imm(bpf_ringbuf_reserve_dynptr),
719 		  __imm(bpf_ringbuf_discard_dynptr),
720 		  __imm_addr(ringbuf)
721 		: __clobber_all
722 	);
723 	return 0;
724 }
725 
726 SEC("?tc")
727 __failure __msg("cannot overwrite referenced dynptr") __log_level(2)
728 int dynptr_pruning_type_confusion(struct __sk_buff *ctx)
729 {
730 	asm volatile (
731 		"r6 = %[array_map4] ll;			\
732 		 r7 = %[ringbuf] ll;			\
733 		 r1 = r6;				\
734 		 r2 = r10;				\
735 		 r2 += -8;				\
736 		 r9 = 0;				\
737 		 *(u64 *)(r2 + 0) = r9;			\
738 		 r3 = r10;				\
739 		 r3 += -24;				\
740 		 r9 = 0xeB9FeB9F;			\
741 		 *(u64 *)(r10 - 16) = r9;		\
742 		 *(u64 *)(r10 - 24) = r9;		\
743 		 r9 = 0;				\
744 		 r4 = 0;				\
745 		 r8 = r2;				\
746 		 call %[bpf_map_update_elem];		\
747 		 r1 = r6;				\
748 		 r2 = r8;				\
749 		 call %[bpf_map_lookup_elem];		\
750 		 if r0 != 0 goto tjmp1;			\
751 		 exit;					\
752 	tjmp1:						\
753 		 r8 = r0;				\
754 		 r1 = r7;				\
755 		 r2 = 8;				\
756 		 r3 = 0;				\
757 		 r4 = r10;				\
758 		 r4 += -16;				\
759 		 r0 = *(u64 *)(r0 + 0);			\
760 		 call %[bpf_ringbuf_reserve_dynptr];	\
761 		 if r0 == 0 goto tjmp2;			\
762 		 r8 = r8;				\
763 		 r8 = r8;				\
764 		 r8 = r8;				\
765 		 r8 = r8;				\
766 		 r8 = r8;				\
767 		 r8 = r8;				\
768 		 r8 = r8;				\
769 		 goto tjmp3;				\
770 	tjmp2:						\
771 		 *(u64 *)(r10 - 8) = r9;		\
772 		 *(u64 *)(r10 - 16) = r9;		\
773 		 r1 = r8;				\
774 		 r1 += 8;				\
775 		 r2 = 0;				\
776 		 r3 = 0;				\
777 		 r4 = r10;				\
778 		 r4 += -16;				\
779 		 call %[bpf_dynptr_from_mem];		\
780 	tjmp3:						\
781 		 r1 = r10;				\
782 		 r1 += -16;				\
783 		 r2 = 0;				\
784 		 call %[bpf_ringbuf_discard_dynptr];	"
785 		:
786 		: __imm(bpf_map_update_elem),
787 		  __imm(bpf_map_lookup_elem),
788 		  __imm(bpf_ringbuf_reserve_dynptr),
789 		  __imm(bpf_dynptr_from_mem),
790 		  __imm(bpf_ringbuf_discard_dynptr),
791 		  __imm_addr(array_map4),
792 		  __imm_addr(ringbuf)
793 		: __clobber_all
794 	);
795 	return 0;
796 }
797 
798 SEC("?tc")
799 __failure __msg("dynptr has to be at a constant offset") __log_level(2)
800 int dynptr_var_off_overwrite(struct __sk_buff *ctx)
801 {
802 	asm volatile (
803 		"r9 = 16;				\
804 		 *(u32 *)(r10 - 4) = r9;		\
805 		 r8 = *(u32 *)(r10 - 4);		\
806 		 if r8 >= 0 goto vjmp1;			\
807 		 r0 = 1;				\
808 		 exit;					\
809 	vjmp1:						\
810 		 if r8 <= 16 goto vjmp2;		\
811 		 r0 = 1;				\
812 		 exit;					\
813 	vjmp2:						\
814 		 r8 &= 16;				\
815 		 r1 = %[ringbuf] ll;			\
816 		 r2 = 8;				\
817 		 r3 = 0;				\
818 		 r4 = r10;				\
819 		 r4 += -32;				\
820 		 r4 += r8;				\
821 		 call %[bpf_ringbuf_reserve_dynptr];	\
822 		 r9 = 0xeB9F;				\
823 		 *(u64 *)(r10 - 16) = r9;		\
824 		 r1 = r10;				\
825 		 r1 += -32;				\
826 		 r1 += r8;				\
827 		 r2 = 0;				\
828 		 call %[bpf_ringbuf_discard_dynptr];	"
829 		:
830 		: __imm(bpf_ringbuf_reserve_dynptr),
831 		  __imm(bpf_ringbuf_discard_dynptr),
832 		  __imm_addr(ringbuf)
833 		: __clobber_all
834 	);
835 	return 0;
836 }
837 
838 SEC("?tc")
839 __failure __msg("cannot overwrite referenced dynptr") __log_level(2)
840 int dynptr_partial_slot_invalidate(struct __sk_buff *ctx)
841 {
842 	asm volatile (
843 		"r6 = %[ringbuf] ll;			\
844 		 r7 = %[array_map4] ll;			\
845 		 r1 = r7;				\
846 		 r2 = r10;				\
847 		 r2 += -8;				\
848 		 r9 = 0;				\
849 		 *(u64 *)(r2 + 0) = r9;			\
850 		 r3 = r2;				\
851 		 r4 = 0;				\
852 		 r8 = r2;				\
853 		 call %[bpf_map_update_elem];		\
854 		 r1 = r7;				\
855 		 r2 = r8;				\
856 		 call %[bpf_map_lookup_elem];		\
857 		 if r0 != 0 goto sjmp1;			\
858 		 exit;					\
859 	sjmp1:						\
860 		 r7 = r0;				\
861 		 r1 = r6;				\
862 		 r2 = 8;				\
863 		 r3 = 0;				\
864 		 r4 = r10;				\
865 		 r4 += -24;				\
866 		 call %[bpf_ringbuf_reserve_dynptr];	\
867 		 *(u64 *)(r10 - 16) = r9;		\
868 		 r1 = r7;				\
869 		 r2 = 8;				\
870 		 r3 = 0;				\
871 		 r4 = r10;				\
872 		 r4 += -16;				\
873 		 call %[bpf_dynptr_from_mem];		\
874 		 r1 = r10;				\
875 		 r1 += -512;				\
876 		 r2 = 488;				\
877 		 r3 = r10;				\
878 		 r3 += -24;				\
879 		 r4 = 0;				\
880 		 r5 = 0;				\
881 		 call %[bpf_dynptr_read];		\
882 		 r8 = 1;				\
883 		 if r0 != 0 goto sjmp2;			\
884 		 r8 = 0;				\
885 	sjmp2:						\
886 		 r1 = r10;				\
887 		 r1 += -24;				\
888 		 r2 = 0;				\
889 		 call %[bpf_ringbuf_discard_dynptr];	"
890 		:
891 		: __imm(bpf_map_update_elem),
892 		  __imm(bpf_map_lookup_elem),
893 		  __imm(bpf_ringbuf_reserve_dynptr),
894 		  __imm(bpf_ringbuf_discard_dynptr),
895 		  __imm(bpf_dynptr_from_mem),
896 		  __imm(bpf_dynptr_read),
897 		  __imm_addr(ringbuf),
898 		  __imm_addr(array_map4)
899 		: __clobber_all
900 	);
901 	return 0;
902 }
903 
904 /* Test that it is allowed to overwrite unreferenced dynptr. */
905 SEC("?raw_tp")
906 __success
907 int dynptr_overwrite_unref(void *ctx)
908 {
909 	struct bpf_dynptr ptr;
910 
911 	if (get_map_val_dynptr(&ptr))
912 		return 0;
913 	if (get_map_val_dynptr(&ptr))
914 		return 0;
915 	if (get_map_val_dynptr(&ptr))
916 		return 0;
917 
918 	return 0;
919 }
920 
921 /* Test that slices are invalidated on reinitializing a dynptr. */
922 SEC("?raw_tp")
923 __failure __msg("invalid mem access 'scalar'")
924 int dynptr_invalidate_slice_reinit(void *ctx)
925 {
926 	struct bpf_dynptr ptr;
927 	__u8 *p;
928 
929 	if (get_map_val_dynptr(&ptr))
930 		return 0;
931 	p = bpf_dynptr_data(&ptr, 0, 1);
932 	if (!p)
933 		return 0;
934 	if (get_map_val_dynptr(&ptr))
935 		return 0;
936 	/* this should fail */
937 	return *p;
938 }
939 
940 /* Invalidation of dynptr slices on destruction of dynptr should not miss
941  * mem_or_null pointers.
942  */
943 SEC("?raw_tp")
944 __failure __msg("R1 type=scalar expected=percpu_ptr_")
945 int dynptr_invalidate_slice_or_null(void *ctx)
946 {
947 	struct bpf_dynptr ptr;
948 	__u8 *p;
949 
950 	if (get_map_val_dynptr(&ptr))
951 		return 0;
952 
953 	p = bpf_dynptr_data(&ptr, 0, 1);
954 	*(__u8 *)&ptr = 0;
955 	/* this should fail */
956 	bpf_this_cpu_ptr(p);
957 	return 0;
958 }
959 
960 /* Destruction of dynptr should also any slices obtained from it */
961 SEC("?raw_tp")
962 __failure __msg("R7 invalid mem access 'scalar'")
963 int dynptr_invalidate_slice_failure(void *ctx)
964 {
965 	struct bpf_dynptr ptr1;
966 	struct bpf_dynptr ptr2;
967 	__u8 *p1, *p2;
968 
969 	if (get_map_val_dynptr(&ptr1))
970 		return 0;
971 	if (get_map_val_dynptr(&ptr2))
972 		return 0;
973 
974 	p1 = bpf_dynptr_data(&ptr1, 0, 1);
975 	if (!p1)
976 		return 0;
977 	p2 = bpf_dynptr_data(&ptr2, 0, 1);
978 	if (!p2)
979 		return 0;
980 
981 	*(__u8 *)&ptr1 = 0;
982 	/* this should fail */
983 	return *p1;
984 }
985 
986 /* Invalidation of slices should be scoped and should not prevent dereferencing
987  * slices of another dynptr after destroying unrelated dynptr
988  */
989 SEC("?raw_tp")
990 __success
991 int dynptr_invalidate_slice_success(void *ctx)
992 {
993 	struct bpf_dynptr ptr1;
994 	struct bpf_dynptr ptr2;
995 	__u8 *p1, *p2;
996 
997 	if (get_map_val_dynptr(&ptr1))
998 		return 1;
999 	if (get_map_val_dynptr(&ptr2))
1000 		return 1;
1001 
1002 	p1 = bpf_dynptr_data(&ptr1, 0, 1);
1003 	if (!p1)
1004 		return 1;
1005 	p2 = bpf_dynptr_data(&ptr2, 0, 1);
1006 	if (!p2)
1007 		return 1;
1008 
1009 	*(__u8 *)&ptr1 = 0;
1010 	return *p2;
1011 }
1012 
1013 /* Overwriting referenced dynptr should be rejected */
1014 SEC("?raw_tp")
1015 __failure __msg("cannot overwrite referenced dynptr")
1016 int dynptr_overwrite_ref(void *ctx)
1017 {
1018 	struct bpf_dynptr ptr;
1019 
1020 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
1021 	/* this should fail */
1022 	if (get_map_val_dynptr(&ptr))
1023 		bpf_ringbuf_discard_dynptr(&ptr, 0);
1024 	return 0;
1025 }
1026 
1027 /* Reject writes to dynptr slot from bpf_dynptr_read */
1028 SEC("?raw_tp")
1029 __failure __msg("potential write to dynptr at off=-16")
1030 int dynptr_read_into_slot(void *ctx)
1031 {
1032 	union {
1033 		struct {
1034 			char _pad[48];
1035 			struct bpf_dynptr ptr;
1036 		};
1037 		char buf[64];
1038 	} data;
1039 
1040 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &data.ptr);
1041 	/* this should fail */
1042 	bpf_dynptr_read(data.buf, sizeof(data.buf), &data.ptr, 0, 0);
1043 
1044 	return 0;
1045 }
1046 
1047 /* Reject writes to dynptr slot for uninit arg */
1048 SEC("?raw_tp")
1049 __failure __msg("potential write to dynptr at off=-16")
1050 int uninit_write_into_slot(void *ctx)
1051 {
1052 	struct {
1053 		char buf[64];
1054 		struct bpf_dynptr ptr;
1055 	} data;
1056 
1057 	bpf_ringbuf_reserve_dynptr(&ringbuf, 80, 0, &data.ptr);
1058 	/* this should fail */
1059 	bpf_get_current_comm(data.buf, 80);
1060 
1061 	return 0;
1062 }
1063 
1064 static int callback(__u32 index, void *data)
1065 {
1066         *(__u32 *)data = 123;
1067 
1068         return 0;
1069 }
1070 
1071 /* If the dynptr is written into in a callback function, its data
1072  * slices should be invalidated as well.
1073  */
1074 SEC("?raw_tp")
1075 __failure __msg("invalid mem access 'scalar'")
1076 int invalid_data_slices(void *ctx)
1077 {
1078 	struct bpf_dynptr ptr;
1079 	__u32 *slice;
1080 
1081 	if (get_map_val_dynptr(&ptr))
1082 		return 0;
1083 
1084 	slice = bpf_dynptr_data(&ptr, 0, sizeof(__u32));
1085 	if (!slice)
1086 		return 0;
1087 
1088 	bpf_loop(10, callback, &ptr, 0);
1089 
1090 	/* this should fail */
1091 	*slice = 1;
1092 
1093 	return 0;
1094 }
1095