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

source code of linux/tools/testing/selftests/bpf/progs/dynptr_fail.c