Loading...
Note: File does not exist in v4.6.
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2022 Facebook */
3
4#include <errno.h>
5#include <string.h>
6#include <stdbool.h>
7#include <linux/bpf.h>
8#include <bpf/bpf_helpers.h>
9#include <bpf/bpf_tracing.h>
10#include <linux/if_ether.h>
11#include "bpf_misc.h"
12#include "bpf_kfuncs.h"
13
14char _license[] SEC("license") = "GPL";
15
16struct test_info {
17 int x;
18 struct bpf_dynptr ptr;
19};
20
21struct {
22 __uint(type, BPF_MAP_TYPE_ARRAY);
23 __uint(max_entries, 1);
24 __type(key, __u32);
25 __type(value, struct bpf_dynptr);
26} array_map1 SEC(".maps");
27
28struct {
29 __uint(type, BPF_MAP_TYPE_ARRAY);
30 __uint(max_entries, 1);
31 __type(key, __u32);
32 __type(value, struct test_info);
33} array_map2 SEC(".maps");
34
35struct {
36 __uint(type, BPF_MAP_TYPE_ARRAY);
37 __uint(max_entries, 1);
38 __type(key, __u32);
39 __type(value, __u32);
40} array_map3 SEC(".maps");
41
42struct {
43 __uint(type, BPF_MAP_TYPE_ARRAY);
44 __uint(max_entries, 1);
45 __type(key, __u32);
46 __type(value, __u64);
47} array_map4 SEC(".maps");
48
49struct sample {
50 int pid;
51 long value;
52 char comm[16];
53};
54
55struct {
56 __uint(type, BPF_MAP_TYPE_RINGBUF);
57 __uint(max_entries, 4096);
58} ringbuf SEC(".maps");
59
60int err, val;
61
62static int get_map_val_dynptr(struct bpf_dynptr *ptr)
63{
64 __u32 key = 0, *map_val;
65
66 bpf_map_update_elem(&array_map3, &key, &val, 0);
67
68 map_val = bpf_map_lookup_elem(&array_map3, &key);
69 if (!map_val)
70 return -ENOENT;
71
72 bpf_dynptr_from_mem(map_val, sizeof(*map_val), 0, ptr);
73
74 return 0;
75}
76
77/* Every bpf_ringbuf_reserve_dynptr call must have a corresponding
78 * bpf_ringbuf_submit/discard_dynptr call
79 */
80SEC("?raw_tp")
81__failure __msg("Unreleased reference id=2")
82int ringbuf_missing_release1(void *ctx)
83{
84 struct bpf_dynptr ptr = {};
85
86 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
87
88 /* missing a call to bpf_ringbuf_discard/submit_dynptr */
89
90 return 0;
91}
92
93SEC("?raw_tp")
94__failure __msg("Unreleased reference id=4")
95int ringbuf_missing_release2(void *ctx)
96{
97 struct bpf_dynptr ptr1, ptr2;
98 struct sample *sample;
99
100 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr1);
101 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
102
103 sample = bpf_dynptr_data(&ptr1, 0, sizeof(*sample));
104 if (!sample) {
105 bpf_ringbuf_discard_dynptr(&ptr1, 0);
106 bpf_ringbuf_discard_dynptr(&ptr2, 0);
107 return 0;
108 }
109
110 bpf_ringbuf_submit_dynptr(&ptr1, 0);
111
112 /* missing a call to bpf_ringbuf_discard/submit_dynptr on ptr2 */
113
114 return 0;
115}
116
117static int missing_release_callback_fn(__u32 index, void *data)
118{
119 struct bpf_dynptr ptr;
120
121 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
122
123 /* missing a call to bpf_ringbuf_discard/submit_dynptr */
124
125 return 0;
126}
127
128/* Any dynptr initialized within a callback must have bpf_dynptr_put called */
129SEC("?raw_tp")
130__failure __msg("Unreleased reference id")
131int ringbuf_missing_release_callback(void *ctx)
132{
133 bpf_loop(10, missing_release_callback_fn, NULL, 0);
134 return 0;
135}
136
137/* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */
138SEC("?raw_tp")
139__failure __msg("arg 1 is an unacquired reference")
140int ringbuf_release_uninit_dynptr(void *ctx)
141{
142 struct bpf_dynptr ptr;
143
144 /* this should fail */
145 bpf_ringbuf_submit_dynptr(&ptr, 0);
146
147 return 0;
148}
149
150/* A dynptr can't be used after it has been invalidated */
151SEC("?raw_tp")
152__failure __msg("Expected an initialized dynptr as arg #2")
153int use_after_invalid(void *ctx)
154{
155 struct bpf_dynptr ptr;
156 char read_data[64];
157
158 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr);
159
160 bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
161
162 bpf_ringbuf_submit_dynptr(&ptr, 0);
163
164 /* this should fail */
165 bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
166
167 return 0;
168}
169
170/* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */
171SEC("?raw_tp")
172__failure __msg("type=mem expected=ringbuf_mem")
173int ringbuf_invalid_api(void *ctx)
174{
175 struct bpf_dynptr ptr;
176 struct sample *sample;
177
178 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
179 sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
180 if (!sample)
181 goto done;
182
183 sample->pid = 123;
184
185 /* invalid API use. need to use dynptr API to submit/discard */
186 bpf_ringbuf_submit(sample, 0);
187
188done:
189 bpf_ringbuf_discard_dynptr(&ptr, 0);
190 return 0;
191}
192
193/* Can't add a dynptr to a map */
194SEC("?raw_tp")
195__failure __msg("invalid indirect read from stack")
196int add_dynptr_to_map1(void *ctx)
197{
198 struct bpf_dynptr ptr;
199 int key = 0;
200
201 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
202
203 /* this should fail */
204 bpf_map_update_elem(&array_map1, &key, &ptr, 0);
205
206 bpf_ringbuf_submit_dynptr(&ptr, 0);
207
208 return 0;
209}
210
211/* Can't add a struct with an embedded dynptr to a map */
212SEC("?raw_tp")
213__failure __msg("invalid indirect read from stack")
214int add_dynptr_to_map2(void *ctx)
215{
216 struct test_info x;
217 int key = 0;
218
219 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &x.ptr);
220
221 /* this should fail */
222 bpf_map_update_elem(&array_map2, &key, &x, 0);
223
224 bpf_ringbuf_submit_dynptr(&x.ptr, 0);
225
226 return 0;
227}
228
229/* A data slice can't be accessed out of bounds */
230SEC("?raw_tp")
231__failure __msg("value is outside of the allowed memory range")
232int data_slice_out_of_bounds_ringbuf(void *ctx)
233{
234 struct bpf_dynptr ptr;
235 void *data;
236
237 bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
238
239 data = bpf_dynptr_data(&ptr, 0, 8);
240 if (!data)
241 goto done;
242
243 /* can't index out of bounds of the data slice */
244 val = *((char *)data + 8);
245
246done:
247 bpf_ringbuf_submit_dynptr(&ptr, 0);
248 return 0;
249}
250
251/* A data slice can't be accessed out of bounds */
252SEC("?tc")
253__failure __msg("value is outside of the allowed memory range")
254int data_slice_out_of_bounds_skb(struct __sk_buff *skb)
255{
256 struct bpf_dynptr ptr;
257 struct ethhdr *hdr;
258 char buffer[sizeof(*hdr)] = {};
259
260 bpf_dynptr_from_skb(skb, 0, &ptr);
261
262 hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
263 if (!hdr)
264 return SK_DROP;
265
266 /* this should fail */
267 *(__u8*)(hdr + 1) = 1;
268
269 return SK_PASS;
270}
271
272SEC("?raw_tp")
273__failure __msg("value is outside of the allowed memory range")
274int data_slice_out_of_bounds_map_value(void *ctx)
275{
276 __u32 map_val;
277 struct bpf_dynptr ptr;
278 void *data;
279
280 get_map_val_dynptr(&ptr);
281
282 data = bpf_dynptr_data(&ptr, 0, sizeof(map_val));
283 if (!data)
284 return 0;
285
286 /* can't index out of bounds of the data slice */
287 val = *((char *)data + (sizeof(map_val) + 1));
288
289 return 0;
290}
291
292/* A data slice can't be used after it has been released */
293SEC("?raw_tp")
294__failure __msg("invalid mem access 'scalar'")
295int data_slice_use_after_release1(void *ctx)
296{
297 struct bpf_dynptr ptr;
298 struct sample *sample;
299
300 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
301 sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
302 if (!sample)
303 goto done;
304
305 sample->pid = 123;
306
307 bpf_ringbuf_submit_dynptr(&ptr, 0);
308
309 /* this should fail */
310 val = sample->pid;
311
312 return 0;
313
314done:
315 bpf_ringbuf_discard_dynptr(&ptr, 0);
316 return 0;
317}
318
319/* A data slice can't be used after it has been released.
320 *
321 * This tests the case where the data slice tracks a dynptr (ptr2)
322 * that is at a non-zero offset from the frame pointer (ptr1 is at fp,
323 * ptr2 is at fp - 16).
324 */
325SEC("?raw_tp")
326__failure __msg("invalid mem access 'scalar'")
327int data_slice_use_after_release2(void *ctx)
328{
329 struct bpf_dynptr ptr1, ptr2;
330 struct sample *sample;
331
332 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1);
333 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
334
335 sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample));
336 if (!sample)
337 goto done;
338
339 sample->pid = 23;
340
341 bpf_ringbuf_submit_dynptr(&ptr2, 0);
342
343 /* this should fail */
344 sample->pid = 23;
345
346 bpf_ringbuf_submit_dynptr(&ptr1, 0);
347
348 return 0;
349
350done:
351 bpf_ringbuf_discard_dynptr(&ptr2, 0);
352 bpf_ringbuf_discard_dynptr(&ptr1, 0);
353 return 0;
354}
355
356/* A data slice must be first checked for NULL */
357SEC("?raw_tp")
358__failure __msg("invalid mem access 'mem_or_null'")
359int data_slice_missing_null_check1(void *ctx)
360{
361 struct bpf_dynptr ptr;
362 void *data;
363
364 bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
365
366 data = bpf_dynptr_data(&ptr, 0, 8);
367
368 /* missing if (!data) check */
369
370 /* this should fail */
371 *(__u8 *)data = 3;
372
373 bpf_ringbuf_submit_dynptr(&ptr, 0);
374 return 0;
375}
376
377/* A data slice can't be dereferenced if it wasn't checked for null */
378SEC("?raw_tp")
379__failure __msg("invalid mem access 'mem_or_null'")
380int data_slice_missing_null_check2(void *ctx)
381{
382 struct bpf_dynptr ptr;
383 __u64 *data1, *data2;
384
385 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
386
387 data1 = bpf_dynptr_data(&ptr, 0, 8);
388 data2 = bpf_dynptr_data(&ptr, 0, 8);
389 if (data1)
390 /* this should fail */
391 *data2 = 3;
392
393 bpf_ringbuf_discard_dynptr(&ptr, 0);
394 return 0;
395}
396
397/* Can't pass in a dynptr as an arg to a helper function that doesn't take in a
398 * dynptr argument
399 */
400SEC("?raw_tp")
401__failure __msg("invalid indirect read from stack")
402int invalid_helper1(void *ctx)
403{
404 struct bpf_dynptr ptr;
405
406 get_map_val_dynptr(&ptr);
407
408 /* this should fail */
409 bpf_strncmp((const char *)&ptr, sizeof(ptr), "hello!");
410
411 return 0;
412}
413
414/* A dynptr can't be passed into a helper function at a non-zero offset */
415SEC("?raw_tp")
416__failure __msg("cannot pass in dynptr at an offset=-8")
417int invalid_helper2(void *ctx)
418{
419 struct bpf_dynptr ptr;
420 char read_data[64];
421
422 get_map_val_dynptr(&ptr);
423
424 /* this should fail */
425 bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0);
426 return 0;
427}
428
429/* A bpf_dynptr is invalidated if it's been written into */
430SEC("?raw_tp")
431__failure __msg("Expected an initialized dynptr as arg #0")
432int invalid_write1(void *ctx)
433{
434 struct bpf_dynptr ptr;
435 void *data;
436 __u8 x = 0;
437
438 get_map_val_dynptr(&ptr);
439
440 memcpy(&ptr, &x, sizeof(x));
441
442 /* this should fail */
443 data = bpf_dynptr_data(&ptr, 0, 1);
444 __sink(data);
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 fixed
451 * offset
452 */
453SEC("?raw_tp")
454__failure __msg("cannot overwrite referenced dynptr")
455int invalid_write2(void *ctx)
456{
457 struct bpf_dynptr ptr;
458 char read_data[64];
459 __u8 x = 0;
460
461 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
462
463 memcpy((void *)&ptr + 8, &x, sizeof(x));
464
465 /* this should fail */
466 bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
467
468 bpf_ringbuf_submit_dynptr(&ptr, 0);
469
470 return 0;
471}
472
473/*
474 * A bpf_dynptr can't be used as a dynptr if it has been written into at a
475 * non-const offset
476 */
477SEC("?raw_tp")
478__failure __msg("cannot overwrite referenced dynptr")
479int invalid_write3(void *ctx)
480{
481 struct bpf_dynptr ptr;
482 char stack_buf[16];
483 unsigned long len;
484 __u8 x = 0;
485
486 bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
487
488 memcpy(stack_buf, &val, sizeof(val));
489 len = stack_buf[0] & 0xf;
490
491 memcpy((void *)&ptr + len, &x, sizeof(x));
492
493 /* this should fail */
494 bpf_ringbuf_submit_dynptr(&ptr, 0);
495
496 return 0;
497}
498
499static int invalid_write4_callback(__u32 index, void *data)
500{
501 *(__u32 *)data = 123;
502
503 return 0;
504}
505
506/* If the dynptr is written into in a callback function, it should
507 * be invalidated as a dynptr
508 */
509SEC("?raw_tp")
510__failure __msg("cannot overwrite referenced dynptr")
511int invalid_write4(void *ctx)
512{
513 struct bpf_dynptr ptr;
514
515 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
516
517 bpf_loop(10, invalid_write4_callback, &ptr, 0);
518
519 /* this should fail */
520 bpf_ringbuf_submit_dynptr(&ptr, 0);
521
522 return 0;
523}
524
525/* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */
526struct bpf_dynptr global_dynptr;
527
528SEC("?raw_tp")
529__failure __msg("type=map_value expected=fp")
530int global(void *ctx)
531{
532 /* this should fail */
533 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &global_dynptr);
534
535 bpf_ringbuf_discard_dynptr(&global_dynptr, 0);
536
537 return 0;
538}
539
540/* A direct read should fail */
541SEC("?raw_tp")
542__failure __msg("invalid read from stack")
543int invalid_read1(void *ctx)
544{
545 struct bpf_dynptr ptr;
546
547 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
548
549 /* this should fail */
550 val = *(int *)&ptr;
551
552 bpf_ringbuf_discard_dynptr(&ptr, 0);
553
554 return 0;
555}
556
557/* A direct read at an offset should fail */
558SEC("?raw_tp")
559__failure __msg("cannot pass in dynptr at an offset")
560int invalid_read2(void *ctx)
561{
562 struct bpf_dynptr ptr;
563 char read_data[64];
564
565 get_map_val_dynptr(&ptr);
566
567 /* this should fail */
568 bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0);
569
570 return 0;
571}
572
573/* A direct read at an offset into the lower stack slot should fail */
574SEC("?raw_tp")
575__failure __msg("invalid read from stack")
576int invalid_read3(void *ctx)
577{
578 struct bpf_dynptr ptr1, ptr2;
579
580 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr1);
581 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr2);
582
583 /* this should fail */
584 memcpy(&val, (void *)&ptr1 + 8, sizeof(val));
585
586 bpf_ringbuf_discard_dynptr(&ptr1, 0);
587 bpf_ringbuf_discard_dynptr(&ptr2, 0);
588
589 return 0;
590}
591
592static int invalid_read4_callback(__u32 index, void *data)
593{
594 /* this should fail */
595 val = *(__u32 *)data;
596
597 return 0;
598}
599
600/* A direct read within a callback function should fail */
601SEC("?raw_tp")
602__failure __msg("invalid read from stack")
603int invalid_read4(void *ctx)
604{
605 struct bpf_dynptr ptr;
606
607 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
608
609 bpf_loop(10, invalid_read4_callback, &ptr, 0);
610
611 bpf_ringbuf_submit_dynptr(&ptr, 0);
612
613 return 0;
614}
615
616/* Initializing a dynptr on an offset should fail */
617SEC("?raw_tp")
618__failure __msg("cannot pass in dynptr at an offset=0")
619int invalid_offset(void *ctx)
620{
621 struct bpf_dynptr ptr;
622
623 /* this should fail */
624 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr + 1);
625
626 bpf_ringbuf_discard_dynptr(&ptr, 0);
627
628 return 0;
629}
630
631/* Can't release a dynptr twice */
632SEC("?raw_tp")
633__failure __msg("arg 1 is an unacquired reference")
634int release_twice(void *ctx)
635{
636 struct bpf_dynptr ptr;
637
638 bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
639
640 bpf_ringbuf_discard_dynptr(&ptr, 0);
641
642 /* this second release should fail */
643 bpf_ringbuf_discard_dynptr(&ptr, 0);
644
645 return 0;
646}
647
648static int release_twice_callback_fn(__u32 index, void *data)
649{
650 /* this should fail */
651 bpf_ringbuf_discard_dynptr(data, 0);
652
653 return 0;
654}
655
656/* Test that releasing a dynptr twice, where one of the releases happens
657 * within a callback function, fails
658 */
659SEC("?raw_tp")
660__failure __msg("arg 1 is an unacquired reference")
661int release_twice_callback(void *ctx)
662{
663 struct bpf_dynptr ptr;
664
665 bpf_ringbuf_reserve_dynptr(&ringbuf, 32, 0, &ptr);
666
667 bpf_ringbuf_discard_dynptr(&ptr, 0);
668
669 bpf_loop(10, release_twice_callback_fn, &ptr, 0);
670
671 return 0;
672}
673
674/* Reject unsupported local mem types for dynptr_from_mem API */
675SEC("?raw_tp")
676__failure __msg("Unsupported reg type fp for bpf_dynptr_from_mem data")
677int dynptr_from_mem_invalid_api(void *ctx)
678{
679 struct bpf_dynptr ptr;
680 int x = 0;
681
682 /* this should fail */
683 bpf_dynptr_from_mem(&x, sizeof(x), 0, &ptr);
684
685 return 0;
686}
687
688SEC("?tc")
689__failure __msg("cannot overwrite referenced dynptr") __log_level(2)
690int dynptr_pruning_overwrite(struct __sk_buff *ctx)
691{
692 asm volatile (
693 "r9 = 0xeB9F; \
694 r6 = %[ringbuf] ll; \
695 r1 = r6; \
696 r2 = 8; \
697 r3 = 0; \
698 r4 = r10; \
699 r4 += -16; \
700 call %[bpf_ringbuf_reserve_dynptr]; \
701 if r0 == 0 goto pjmp1; \
702 goto pjmp2; \
703 pjmp1: \
704 *(u64 *)(r10 - 16) = r9; \
705 pjmp2: \
706 r1 = r10; \
707 r1 += -16; \
708 r2 = 0; \
709 call %[bpf_ringbuf_discard_dynptr]; "
710 :
711 : __imm(bpf_ringbuf_reserve_dynptr),
712 __imm(bpf_ringbuf_discard_dynptr),
713 __imm_addr(ringbuf)
714 : __clobber_all
715 );
716 return 0;
717}
718
719SEC("?tc")
720__success __msg("12: safe") __log_level(2)
721int dynptr_pruning_stacksafe(struct __sk_buff *ctx)
722{
723 asm volatile (
724 "r9 = 0xeB9F; \
725 r6 = %[ringbuf] ll; \
726 r1 = r6; \
727 r2 = 8; \
728 r3 = 0; \
729 r4 = r10; \
730 r4 += -16; \
731 call %[bpf_ringbuf_reserve_dynptr]; \
732 if r0 == 0 goto stjmp1; \
733 goto stjmp2; \
734 stjmp1: \
735 r9 = r9; \
736 stjmp2: \
737 r1 = r10; \
738 r1 += -16; \
739 r2 = 0; \
740 call %[bpf_ringbuf_discard_dynptr]; "
741 :
742 : __imm(bpf_ringbuf_reserve_dynptr),
743 __imm(bpf_ringbuf_discard_dynptr),
744 __imm_addr(ringbuf)
745 : __clobber_all
746 );
747 return 0;
748}
749
750SEC("?tc")
751__failure __msg("cannot overwrite referenced dynptr") __log_level(2)
752int dynptr_pruning_type_confusion(struct __sk_buff *ctx)
753{
754 asm volatile (
755 "r6 = %[array_map4] ll; \
756 r7 = %[ringbuf] ll; \
757 r1 = r6; \
758 r2 = r10; \
759 r2 += -8; \
760 r9 = 0; \
761 *(u64 *)(r2 + 0) = r9; \
762 r3 = r10; \
763 r3 += -24; \
764 r9 = 0xeB9FeB9F; \
765 *(u64 *)(r10 - 16) = r9; \
766 *(u64 *)(r10 - 24) = r9; \
767 r9 = 0; \
768 r4 = 0; \
769 r8 = r2; \
770 call %[bpf_map_update_elem]; \
771 r1 = r6; \
772 r2 = r8; \
773 call %[bpf_map_lookup_elem]; \
774 if r0 != 0 goto tjmp1; \
775 exit; \
776 tjmp1: \
777 r8 = r0; \
778 r1 = r7; \
779 r2 = 8; \
780 r3 = 0; \
781 r4 = r10; \
782 r4 += -16; \
783 r0 = *(u64 *)(r0 + 0); \
784 call %[bpf_ringbuf_reserve_dynptr]; \
785 if r0 == 0 goto tjmp2; \
786 r8 = r8; \
787 r8 = r8; \
788 r8 = r8; \
789 r8 = r8; \
790 r8 = r8; \
791 r8 = r8; \
792 r8 = r8; \
793 goto tjmp3; \
794 tjmp2: \
795 *(u64 *)(r10 - 8) = r9; \
796 *(u64 *)(r10 - 16) = r9; \
797 r1 = r8; \
798 r1 += 8; \
799 r2 = 0; \
800 r3 = 0; \
801 r4 = r10; \
802 r4 += -16; \
803 call %[bpf_dynptr_from_mem]; \
804 tjmp3: \
805 r1 = r10; \
806 r1 += -16; \
807 r2 = 0; \
808 call %[bpf_ringbuf_discard_dynptr]; "
809 :
810 : __imm(bpf_map_update_elem),
811 __imm(bpf_map_lookup_elem),
812 __imm(bpf_ringbuf_reserve_dynptr),
813 __imm(bpf_dynptr_from_mem),
814 __imm(bpf_ringbuf_discard_dynptr),
815 __imm_addr(array_map4),
816 __imm_addr(ringbuf)
817 : __clobber_all
818 );
819 return 0;
820}
821
822SEC("?tc")
823__failure __msg("dynptr has to be at a constant offset") __log_level(2)
824int dynptr_var_off_overwrite(struct __sk_buff *ctx)
825{
826 asm volatile (
827 "r9 = 16; \
828 *(u32 *)(r10 - 4) = r9; \
829 r8 = *(u32 *)(r10 - 4); \
830 if r8 >= 0 goto vjmp1; \
831 r0 = 1; \
832 exit; \
833 vjmp1: \
834 if r8 <= 16 goto vjmp2; \
835 r0 = 1; \
836 exit; \
837 vjmp2: \
838 r8 &= 16; \
839 r1 = %[ringbuf] ll; \
840 r2 = 8; \
841 r3 = 0; \
842 r4 = r10; \
843 r4 += -32; \
844 r4 += r8; \
845 call %[bpf_ringbuf_reserve_dynptr]; \
846 r9 = 0xeB9F; \
847 *(u64 *)(r10 - 16) = r9; \
848 r1 = r10; \
849 r1 += -32; \
850 r1 += r8; \
851 r2 = 0; \
852 call %[bpf_ringbuf_discard_dynptr]; "
853 :
854 : __imm(bpf_ringbuf_reserve_dynptr),
855 __imm(bpf_ringbuf_discard_dynptr),
856 __imm_addr(ringbuf)
857 : __clobber_all
858 );
859 return 0;
860}
861
862SEC("?tc")
863__failure __msg("cannot overwrite referenced dynptr") __log_level(2)
864int dynptr_partial_slot_invalidate(struct __sk_buff *ctx)
865{
866 asm volatile (
867 "r6 = %[ringbuf] ll; \
868 r7 = %[array_map4] ll; \
869 r1 = r7; \
870 r2 = r10; \
871 r2 += -8; \
872 r9 = 0; \
873 *(u64 *)(r2 + 0) = r9; \
874 r3 = r2; \
875 r4 = 0; \
876 r8 = r2; \
877 call %[bpf_map_update_elem]; \
878 r1 = r7; \
879 r2 = r8; \
880 call %[bpf_map_lookup_elem]; \
881 if r0 != 0 goto sjmp1; \
882 exit; \
883 sjmp1: \
884 r7 = r0; \
885 r1 = r6; \
886 r2 = 8; \
887 r3 = 0; \
888 r4 = r10; \
889 r4 += -24; \
890 call %[bpf_ringbuf_reserve_dynptr]; \
891 *(u64 *)(r10 - 16) = r9; \
892 r1 = r7; \
893 r2 = 8; \
894 r3 = 0; \
895 r4 = r10; \
896 r4 += -16; \
897 call %[bpf_dynptr_from_mem]; \
898 r1 = r10; \
899 r1 += -512; \
900 r2 = 488; \
901 r3 = r10; \
902 r3 += -24; \
903 r4 = 0; \
904 r5 = 0; \
905 call %[bpf_dynptr_read]; \
906 r8 = 1; \
907 if r0 != 0 goto sjmp2; \
908 r8 = 0; \
909 sjmp2: \
910 r1 = r10; \
911 r1 += -24; \
912 r2 = 0; \
913 call %[bpf_ringbuf_discard_dynptr]; "
914 :
915 : __imm(bpf_map_update_elem),
916 __imm(bpf_map_lookup_elem),
917 __imm(bpf_ringbuf_reserve_dynptr),
918 __imm(bpf_ringbuf_discard_dynptr),
919 __imm(bpf_dynptr_from_mem),
920 __imm(bpf_dynptr_read),
921 __imm_addr(ringbuf),
922 __imm_addr(array_map4)
923 : __clobber_all
924 );
925 return 0;
926}
927
928/* Test that it is allowed to overwrite unreferenced dynptr. */
929SEC("?raw_tp")
930__success
931int dynptr_overwrite_unref(void *ctx)
932{
933 struct bpf_dynptr ptr;
934
935 if (get_map_val_dynptr(&ptr))
936 return 0;
937 if (get_map_val_dynptr(&ptr))
938 return 0;
939 if (get_map_val_dynptr(&ptr))
940 return 0;
941
942 return 0;
943}
944
945/* Test that slices are invalidated on reinitializing a dynptr. */
946SEC("?raw_tp")
947__failure __msg("invalid mem access 'scalar'")
948int dynptr_invalidate_slice_reinit(void *ctx)
949{
950 struct bpf_dynptr ptr;
951 __u8 *p;
952
953 if (get_map_val_dynptr(&ptr))
954 return 0;
955 p = bpf_dynptr_data(&ptr, 0, 1);
956 if (!p)
957 return 0;
958 if (get_map_val_dynptr(&ptr))
959 return 0;
960 /* this should fail */
961 return *p;
962}
963
964/* Invalidation of dynptr slices on destruction of dynptr should not miss
965 * mem_or_null pointers.
966 */
967SEC("?raw_tp")
968__failure __msg("R{{[0-9]+}} type=scalar expected=percpu_ptr_")
969int dynptr_invalidate_slice_or_null(void *ctx)
970{
971 struct bpf_dynptr ptr;
972 __u8 *p;
973
974 if (get_map_val_dynptr(&ptr))
975 return 0;
976
977 p = bpf_dynptr_data(&ptr, 0, 1);
978 *(__u8 *)&ptr = 0;
979 /* this should fail */
980 bpf_this_cpu_ptr(p);
981 return 0;
982}
983
984/* Destruction of dynptr should also any slices obtained from it */
985SEC("?raw_tp")
986__failure __msg("R{{[0-9]+}} invalid mem access 'scalar'")
987int dynptr_invalidate_slice_failure(void *ctx)
988{
989 struct bpf_dynptr ptr1;
990 struct bpf_dynptr ptr2;
991 __u8 *p1, *p2;
992
993 if (get_map_val_dynptr(&ptr1))
994 return 0;
995 if (get_map_val_dynptr(&ptr2))
996 return 0;
997
998 p1 = bpf_dynptr_data(&ptr1, 0, 1);
999 if (!p1)
1000 return 0;
1001 p2 = bpf_dynptr_data(&ptr2, 0, 1);
1002 if (!p2)
1003 return 0;
1004
1005 *(__u8 *)&ptr1 = 0;
1006 /* this should fail */
1007 return *p1;
1008}
1009
1010/* Invalidation of slices should be scoped and should not prevent dereferencing
1011 * slices of another dynptr after destroying unrelated dynptr
1012 */
1013SEC("?raw_tp")
1014__success
1015int dynptr_invalidate_slice_success(void *ctx)
1016{
1017 struct bpf_dynptr ptr1;
1018 struct bpf_dynptr ptr2;
1019 __u8 *p1, *p2;
1020
1021 if (get_map_val_dynptr(&ptr1))
1022 return 1;
1023 if (get_map_val_dynptr(&ptr2))
1024 return 1;
1025
1026 p1 = bpf_dynptr_data(&ptr1, 0, 1);
1027 if (!p1)
1028 return 1;
1029 p2 = bpf_dynptr_data(&ptr2, 0, 1);
1030 if (!p2)
1031 return 1;
1032
1033 *(__u8 *)&ptr1 = 0;
1034 return *p2;
1035}
1036
1037/* Overwriting referenced dynptr should be rejected */
1038SEC("?raw_tp")
1039__failure __msg("cannot overwrite referenced dynptr")
1040int dynptr_overwrite_ref(void *ctx)
1041{
1042 struct bpf_dynptr ptr;
1043
1044 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
1045 /* this should fail */
1046 if (get_map_val_dynptr(&ptr))
1047 bpf_ringbuf_discard_dynptr(&ptr, 0);
1048 return 0;
1049}
1050
1051/* Reject writes to dynptr slot from bpf_dynptr_read */
1052SEC("?raw_tp")
1053__failure __msg("potential write to dynptr at off=-16")
1054int dynptr_read_into_slot(void *ctx)
1055{
1056 union {
1057 struct {
1058 char _pad[48];
1059 struct bpf_dynptr ptr;
1060 };
1061 char buf[64];
1062 } data;
1063
1064 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &data.ptr);
1065 /* this should fail */
1066 bpf_dynptr_read(data.buf, sizeof(data.buf), &data.ptr, 0, 0);
1067
1068 return 0;
1069}
1070
1071/* bpf_dynptr_slice()s are read-only and cannot be written to */
1072SEC("?tc")
1073__failure __msg("R{{[0-9]+}} cannot write into rdonly_mem")
1074int skb_invalid_slice_write(struct __sk_buff *skb)
1075{
1076 struct bpf_dynptr ptr;
1077 struct ethhdr *hdr;
1078 char buffer[sizeof(*hdr)] = {};
1079
1080 bpf_dynptr_from_skb(skb, 0, &ptr);
1081
1082 hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1083 if (!hdr)
1084 return SK_DROP;
1085
1086 /* this should fail */
1087 hdr->h_proto = 1;
1088
1089 return SK_PASS;
1090}
1091
1092/* The read-only data slice is invalidated whenever a helper changes packet data */
1093SEC("?tc")
1094__failure __msg("invalid mem access 'scalar'")
1095int skb_invalid_data_slice1(struct __sk_buff *skb)
1096{
1097 struct bpf_dynptr ptr;
1098 struct ethhdr *hdr;
1099 char buffer[sizeof(*hdr)] = {};
1100
1101 bpf_dynptr_from_skb(skb, 0, &ptr);
1102
1103 hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1104 if (!hdr)
1105 return SK_DROP;
1106
1107 val = hdr->h_proto;
1108
1109 if (bpf_skb_pull_data(skb, skb->len))
1110 return SK_DROP;
1111
1112 /* this should fail */
1113 val = hdr->h_proto;
1114
1115 return SK_PASS;
1116}
1117
1118/* The read-write data slice is invalidated whenever a helper changes packet data */
1119SEC("?tc")
1120__failure __msg("invalid mem access 'scalar'")
1121int skb_invalid_data_slice2(struct __sk_buff *skb)
1122{
1123 struct bpf_dynptr ptr;
1124 struct ethhdr *hdr;
1125 char buffer[sizeof(*hdr)] = {};
1126
1127 bpf_dynptr_from_skb(skb, 0, &ptr);
1128
1129 hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1130 if (!hdr)
1131 return SK_DROP;
1132
1133 hdr->h_proto = 123;
1134
1135 if (bpf_skb_pull_data(skb, skb->len))
1136 return SK_DROP;
1137
1138 /* this should fail */
1139 hdr->h_proto = 1;
1140
1141 return SK_PASS;
1142}
1143
1144/* The read-only data slice is invalidated whenever bpf_dynptr_write() is called */
1145SEC("?tc")
1146__failure __msg("invalid mem access 'scalar'")
1147int skb_invalid_data_slice3(struct __sk_buff *skb)
1148{
1149 char write_data[64] = "hello there, world!!";
1150 struct bpf_dynptr ptr;
1151 struct ethhdr *hdr;
1152 char buffer[sizeof(*hdr)] = {};
1153
1154 bpf_dynptr_from_skb(skb, 0, &ptr);
1155
1156 hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1157 if (!hdr)
1158 return SK_DROP;
1159
1160 val = hdr->h_proto;
1161
1162 bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0);
1163
1164 /* this should fail */
1165 val = hdr->h_proto;
1166
1167 return SK_PASS;
1168}
1169
1170/* The read-write data slice is invalidated whenever bpf_dynptr_write() is called */
1171SEC("?tc")
1172__failure __msg("invalid mem access 'scalar'")
1173int skb_invalid_data_slice4(struct __sk_buff *skb)
1174{
1175 char write_data[64] = "hello there, world!!";
1176 struct bpf_dynptr ptr;
1177 struct ethhdr *hdr;
1178 char buffer[sizeof(*hdr)] = {};
1179
1180 bpf_dynptr_from_skb(skb, 0, &ptr);
1181 hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1182 if (!hdr)
1183 return SK_DROP;
1184
1185 hdr->h_proto = 123;
1186
1187 bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0);
1188
1189 /* this should fail */
1190 hdr->h_proto = 1;
1191
1192 return SK_PASS;
1193}
1194
1195/* The read-only data slice is invalidated whenever a helper changes packet data */
1196SEC("?xdp")
1197__failure __msg("invalid mem access 'scalar'")
1198int xdp_invalid_data_slice1(struct xdp_md *xdp)
1199{
1200 struct bpf_dynptr ptr;
1201 struct ethhdr *hdr;
1202 char buffer[sizeof(*hdr)] = {};
1203
1204 bpf_dynptr_from_xdp(xdp, 0, &ptr);
1205 hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1206 if (!hdr)
1207 return SK_DROP;
1208
1209 val = hdr->h_proto;
1210
1211 if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))
1212 return XDP_DROP;
1213
1214 /* this should fail */
1215 val = hdr->h_proto;
1216
1217 return XDP_PASS;
1218}
1219
1220/* The read-write data slice is invalidated whenever a helper changes packet data */
1221SEC("?xdp")
1222__failure __msg("invalid mem access 'scalar'")
1223int xdp_invalid_data_slice2(struct xdp_md *xdp)
1224{
1225 struct bpf_dynptr ptr;
1226 struct ethhdr *hdr;
1227 char buffer[sizeof(*hdr)] = {};
1228
1229 bpf_dynptr_from_xdp(xdp, 0, &ptr);
1230 hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1231 if (!hdr)
1232 return SK_DROP;
1233
1234 hdr->h_proto = 9;
1235
1236 if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))
1237 return XDP_DROP;
1238
1239 /* this should fail */
1240 hdr->h_proto = 1;
1241
1242 return XDP_PASS;
1243}
1244
1245/* Only supported prog type can create skb-type dynptrs */
1246SEC("?raw_tp")
1247__failure __msg("calling kernel function bpf_dynptr_from_skb is not allowed")
1248int skb_invalid_ctx(void *ctx)
1249{
1250 struct bpf_dynptr ptr;
1251
1252 /* this should fail */
1253 bpf_dynptr_from_skb(ctx, 0, &ptr);
1254
1255 return 0;
1256}
1257
1258SEC("fentry/skb_tx_error")
1259__failure __msg("must be referenced or trusted")
1260int BPF_PROG(skb_invalid_ctx_fentry, void *skb)
1261{
1262 struct bpf_dynptr ptr;
1263
1264 /* this should fail */
1265 bpf_dynptr_from_skb(skb, 0, &ptr);
1266
1267 return 0;
1268}
1269
1270SEC("fexit/skb_tx_error")
1271__failure __msg("must be referenced or trusted")
1272int BPF_PROG(skb_invalid_ctx_fexit, void *skb)
1273{
1274 struct bpf_dynptr ptr;
1275
1276 /* this should fail */
1277 bpf_dynptr_from_skb(skb, 0, &ptr);
1278
1279 return 0;
1280}
1281
1282/* Reject writes to dynptr slot for uninit arg */
1283SEC("?raw_tp")
1284__failure __msg("potential write to dynptr at off=-16")
1285int uninit_write_into_slot(void *ctx)
1286{
1287 struct {
1288 char buf[64];
1289 struct bpf_dynptr ptr;
1290 } data;
1291
1292 bpf_ringbuf_reserve_dynptr(&ringbuf, 80, 0, &data.ptr);
1293 /* this should fail */
1294 bpf_get_current_comm(data.buf, 80);
1295
1296 return 0;
1297}
1298
1299/* Only supported prog type can create xdp-type dynptrs */
1300SEC("?raw_tp")
1301__failure __msg("calling kernel function bpf_dynptr_from_xdp is not allowed")
1302int xdp_invalid_ctx(void *ctx)
1303{
1304 struct bpf_dynptr ptr;
1305
1306 /* this should fail */
1307 bpf_dynptr_from_xdp(ctx, 0, &ptr);
1308
1309 return 0;
1310}
1311
1312__u32 hdr_size = sizeof(struct ethhdr);
1313/* Can't pass in variable-sized len to bpf_dynptr_slice */
1314SEC("?tc")
1315__failure __msg("unbounded memory access")
1316int dynptr_slice_var_len1(struct __sk_buff *skb)
1317{
1318 struct bpf_dynptr ptr;
1319 struct ethhdr *hdr;
1320 char buffer[sizeof(*hdr)] = {};
1321
1322 bpf_dynptr_from_skb(skb, 0, &ptr);
1323
1324 /* this should fail */
1325 hdr = bpf_dynptr_slice(&ptr, 0, buffer, hdr_size);
1326 if (!hdr)
1327 return SK_DROP;
1328
1329 return SK_PASS;
1330}
1331
1332/* Can't pass in variable-sized len to bpf_dynptr_slice */
1333SEC("?tc")
1334__failure __msg("must be a known constant")
1335int dynptr_slice_var_len2(struct __sk_buff *skb)
1336{
1337 char buffer[sizeof(struct ethhdr)] = {};
1338 struct bpf_dynptr ptr;
1339 struct ethhdr *hdr;
1340
1341 bpf_dynptr_from_skb(skb, 0, &ptr);
1342
1343 if (hdr_size <= sizeof(buffer)) {
1344 /* this should fail */
1345 hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, hdr_size);
1346 if (!hdr)
1347 return SK_DROP;
1348 hdr->h_proto = 12;
1349 }
1350
1351 return SK_PASS;
1352}
1353
1354static int callback(__u32 index, void *data)
1355{
1356 *(__u32 *)data = 123;
1357
1358 return 0;
1359}
1360
1361/* If the dynptr is written into in a callback function, its data
1362 * slices should be invalidated as well.
1363 */
1364SEC("?raw_tp")
1365__failure __msg("invalid mem access 'scalar'")
1366int invalid_data_slices(void *ctx)
1367{
1368 struct bpf_dynptr ptr;
1369 __u32 *slice;
1370
1371 if (get_map_val_dynptr(&ptr))
1372 return 0;
1373
1374 slice = bpf_dynptr_data(&ptr, 0, sizeof(__u32));
1375 if (!slice)
1376 return 0;
1377
1378 bpf_loop(10, callback, &ptr, 0);
1379
1380 /* this should fail */
1381 *slice = 1;
1382
1383 return 0;
1384}
1385
1386/* Program types that don't allow writes to packet data should fail if
1387 * bpf_dynptr_slice_rdwr is called
1388 */
1389SEC("cgroup_skb/ingress")
1390__failure __msg("the prog does not allow writes to packet data")
1391int invalid_slice_rdwr_rdonly(struct __sk_buff *skb)
1392{
1393 char buffer[sizeof(struct ethhdr)] = {};
1394 struct bpf_dynptr ptr;
1395 struct ethhdr *hdr;
1396
1397 bpf_dynptr_from_skb(skb, 0, &ptr);
1398
1399 /* this should fail since cgroup_skb doesn't allow
1400 * changing packet data
1401 */
1402 hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1403 __sink(hdr);
1404
1405 return 0;
1406}
1407
1408/* bpf_dynptr_adjust can only be called on initialized dynptrs */
1409SEC("?raw_tp")
1410__failure __msg("Expected an initialized dynptr as arg #0")
1411int dynptr_adjust_invalid(void *ctx)
1412{
1413 struct bpf_dynptr ptr = {};
1414
1415 /* this should fail */
1416 bpf_dynptr_adjust(&ptr, 1, 2);
1417
1418 return 0;
1419}
1420
1421/* bpf_dynptr_is_null can only be called on initialized dynptrs */
1422SEC("?raw_tp")
1423__failure __msg("Expected an initialized dynptr as arg #0")
1424int dynptr_is_null_invalid(void *ctx)
1425{
1426 struct bpf_dynptr ptr = {};
1427
1428 /* this should fail */
1429 bpf_dynptr_is_null(&ptr);
1430
1431 return 0;
1432}
1433
1434/* bpf_dynptr_is_rdonly can only be called on initialized dynptrs */
1435SEC("?raw_tp")
1436__failure __msg("Expected an initialized dynptr as arg #0")
1437int dynptr_is_rdonly_invalid(void *ctx)
1438{
1439 struct bpf_dynptr ptr = {};
1440
1441 /* this should fail */
1442 bpf_dynptr_is_rdonly(&ptr);
1443
1444 return 0;
1445}
1446
1447/* bpf_dynptr_size can only be called on initialized dynptrs */
1448SEC("?raw_tp")
1449__failure __msg("Expected an initialized dynptr as arg #0")
1450int dynptr_size_invalid(void *ctx)
1451{
1452 struct bpf_dynptr ptr = {};
1453
1454 /* this should fail */
1455 bpf_dynptr_size(&ptr);
1456
1457 return 0;
1458}
1459
1460/* Only initialized dynptrs can be cloned */
1461SEC("?raw_tp")
1462__failure __msg("Expected an initialized dynptr as arg #0")
1463int clone_invalid1(void *ctx)
1464{
1465 struct bpf_dynptr ptr1 = {};
1466 struct bpf_dynptr ptr2;
1467
1468 /* this should fail */
1469 bpf_dynptr_clone(&ptr1, &ptr2);
1470
1471 return 0;
1472}
1473
1474/* Can't overwrite an existing dynptr when cloning */
1475SEC("?xdp")
1476__failure __msg("cannot overwrite referenced dynptr")
1477int clone_invalid2(struct xdp_md *xdp)
1478{
1479 struct bpf_dynptr ptr1;
1480 struct bpf_dynptr clone;
1481
1482 bpf_dynptr_from_xdp(xdp, 0, &ptr1);
1483
1484 bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &clone);
1485
1486 /* this should fail */
1487 bpf_dynptr_clone(&ptr1, &clone);
1488
1489 bpf_ringbuf_submit_dynptr(&clone, 0);
1490
1491 return 0;
1492}
1493
1494/* Invalidating a dynptr should invalidate its clones */
1495SEC("?raw_tp")
1496__failure __msg("Expected an initialized dynptr as arg #2")
1497int clone_invalidate1(void *ctx)
1498{
1499 struct bpf_dynptr clone;
1500 struct bpf_dynptr ptr;
1501 char read_data[64];
1502
1503 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1504
1505 bpf_dynptr_clone(&ptr, &clone);
1506
1507 bpf_ringbuf_submit_dynptr(&ptr, 0);
1508
1509 /* this should fail */
1510 bpf_dynptr_read(read_data, sizeof(read_data), &clone, 0, 0);
1511
1512 return 0;
1513}
1514
1515/* Invalidating a dynptr should invalidate its parent */
1516SEC("?raw_tp")
1517__failure __msg("Expected an initialized dynptr as arg #2")
1518int clone_invalidate2(void *ctx)
1519{
1520 struct bpf_dynptr ptr;
1521 struct bpf_dynptr clone;
1522 char read_data[64];
1523
1524 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1525
1526 bpf_dynptr_clone(&ptr, &clone);
1527
1528 bpf_ringbuf_submit_dynptr(&clone, 0);
1529
1530 /* this should fail */
1531 bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
1532
1533 return 0;
1534}
1535
1536/* Invalidating a dynptr should invalidate its siblings */
1537SEC("?raw_tp")
1538__failure __msg("Expected an initialized dynptr as arg #2")
1539int clone_invalidate3(void *ctx)
1540{
1541 struct bpf_dynptr ptr;
1542 struct bpf_dynptr clone1;
1543 struct bpf_dynptr clone2;
1544 char read_data[64];
1545
1546 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1547
1548 bpf_dynptr_clone(&ptr, &clone1);
1549
1550 bpf_dynptr_clone(&ptr, &clone2);
1551
1552 bpf_ringbuf_submit_dynptr(&clone2, 0);
1553
1554 /* this should fail */
1555 bpf_dynptr_read(read_data, sizeof(read_data), &clone1, 0, 0);
1556
1557 return 0;
1558}
1559
1560/* Invalidating a dynptr should invalidate any data slices
1561 * of its clones
1562 */
1563SEC("?raw_tp")
1564__failure __msg("invalid mem access 'scalar'")
1565int clone_invalidate4(void *ctx)
1566{
1567 struct bpf_dynptr ptr;
1568 struct bpf_dynptr clone;
1569 int *data;
1570
1571 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1572
1573 bpf_dynptr_clone(&ptr, &clone);
1574 data = bpf_dynptr_data(&clone, 0, sizeof(val));
1575 if (!data)
1576 return 0;
1577
1578 bpf_ringbuf_submit_dynptr(&ptr, 0);
1579
1580 /* this should fail */
1581 *data = 123;
1582
1583 return 0;
1584}
1585
1586/* Invalidating a dynptr should invalidate any data slices
1587 * of its parent
1588 */
1589SEC("?raw_tp")
1590__failure __msg("invalid mem access 'scalar'")
1591int clone_invalidate5(void *ctx)
1592{
1593 struct bpf_dynptr ptr;
1594 struct bpf_dynptr clone;
1595 int *data;
1596
1597 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1598 data = bpf_dynptr_data(&ptr, 0, sizeof(val));
1599 if (!data)
1600 return 0;
1601
1602 bpf_dynptr_clone(&ptr, &clone);
1603
1604 bpf_ringbuf_submit_dynptr(&clone, 0);
1605
1606 /* this should fail */
1607 *data = 123;
1608
1609 return 0;
1610}
1611
1612/* Invalidating a dynptr should invalidate any data slices
1613 * of its sibling
1614 */
1615SEC("?raw_tp")
1616__failure __msg("invalid mem access 'scalar'")
1617int clone_invalidate6(void *ctx)
1618{
1619 struct bpf_dynptr ptr;
1620 struct bpf_dynptr clone1;
1621 struct bpf_dynptr clone2;
1622 int *data;
1623
1624 bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1625
1626 bpf_dynptr_clone(&ptr, &clone1);
1627
1628 bpf_dynptr_clone(&ptr, &clone2);
1629
1630 data = bpf_dynptr_data(&clone1, 0, sizeof(val));
1631 if (!data)
1632 return 0;
1633
1634 bpf_ringbuf_submit_dynptr(&clone2, 0);
1635
1636 /* this should fail */
1637 *data = 123;
1638
1639 return 0;
1640}
1641
1642/* A skb clone's data slices should be invalid anytime packet data changes */
1643SEC("?tc")
1644__failure __msg("invalid mem access 'scalar'")
1645int clone_skb_packet_data(struct __sk_buff *skb)
1646{
1647 char buffer[sizeof(__u32)] = {};
1648 struct bpf_dynptr clone;
1649 struct bpf_dynptr ptr;
1650 __u32 *data;
1651
1652 bpf_dynptr_from_skb(skb, 0, &ptr);
1653
1654 bpf_dynptr_clone(&ptr, &clone);
1655 data = bpf_dynptr_slice_rdwr(&clone, 0, buffer, sizeof(buffer));
1656 if (!data)
1657 return XDP_DROP;
1658
1659 if (bpf_skb_pull_data(skb, skb->len))
1660 return SK_DROP;
1661
1662 /* this should fail */
1663 *data = 123;
1664
1665 return 0;
1666}
1667
1668/* A xdp clone's data slices should be invalid anytime packet data changes */
1669SEC("?xdp")
1670__failure __msg("invalid mem access 'scalar'")
1671int clone_xdp_packet_data(struct xdp_md *xdp)
1672{
1673 char buffer[sizeof(__u32)] = {};
1674 struct bpf_dynptr clone;
1675 struct bpf_dynptr ptr;
1676 struct ethhdr *hdr;
1677 __u32 *data;
1678
1679 bpf_dynptr_from_xdp(xdp, 0, &ptr);
1680
1681 bpf_dynptr_clone(&ptr, &clone);
1682 data = bpf_dynptr_slice_rdwr(&clone, 0, buffer, sizeof(buffer));
1683 if (!data)
1684 return XDP_DROP;
1685
1686 if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))
1687 return XDP_DROP;
1688
1689 /* this should fail */
1690 *data = 123;
1691
1692 return 0;
1693}
1694
1695/* Buffers that are provided must be sufficiently long */
1696SEC("?cgroup_skb/egress")
1697__failure __msg("memory, len pair leads to invalid memory access")
1698int test_dynptr_skb_small_buff(struct __sk_buff *skb)
1699{
1700 struct bpf_dynptr ptr;
1701 char buffer[8] = {};
1702 __u64 *data;
1703
1704 if (bpf_dynptr_from_skb(skb, 0, &ptr)) {
1705 err = 1;
1706 return 1;
1707 }
1708
1709 /* This may return NULL. SKB may require a buffer */
1710 data = bpf_dynptr_slice(&ptr, 0, buffer, 9);
1711
1712 return !!data;
1713}
1714
1715__noinline long global_call_bpf_dynptr(const struct bpf_dynptr *dynptr)
1716{
1717 long ret = 0;
1718 /* Avoid leaving this global function empty to avoid having the compiler
1719 * optimize away the call to this global function.
1720 */
1721 __sink(ret);
1722 return ret;
1723}
1724
1725SEC("?raw_tp")
1726__failure __msg("arg#0 expected pointer to stack or const struct bpf_dynptr")
1727int test_dynptr_reg_type(void *ctx)
1728{
1729 struct task_struct *current = NULL;
1730 /* R1 should be holding a PTR_TO_BTF_ID, so this shouldn't be a
1731 * reg->type that can be passed to a function accepting a
1732 * ARG_PTR_TO_DYNPTR | MEM_RDONLY. process_dynptr_func() should catch
1733 * this.
1734 */
1735 global_call_bpf_dynptr((const struct bpf_dynptr *)current);
1736 return 0;
1737}