1
1
// SPDX-License-Identifier: GPL-2.0
2
2
/* Copyright (c) 2022 Facebook */
3
3
4
+ #include <vmlinux.h>
4
5
#include <string.h>
5
6
#include <stdbool.h>
6
- #include <linux/bpf.h>
7
7
#include <bpf/bpf_helpers.h>
8
8
#include <bpf/bpf_tracing.h>
9
9
#include "bpf_misc.h"
10
- #include "bpf_kfuncs.h"
11
10
#include "errno.h"
12
11
13
12
char _license [] SEC ("license" ) = "GPL" ;
14
13
15
14
int pid , err , val ;
16
15
17
- struct sample {
16
+ struct ringbuf_sample {
18
17
int pid ;
19
18
int seq ;
20
19
long value ;
@@ -121,7 +120,7 @@ int test_dynptr_data(void *ctx)
121
120
122
121
static int ringbuf_callback (__u32 index , void * data )
123
122
{
124
- struct sample * sample ;
123
+ struct ringbuf_sample * sample ;
125
124
126
125
struct bpf_dynptr * ptr = (struct bpf_dynptr * )data ;
127
126
@@ -138,7 +137,7 @@ SEC("?tp/syscalls/sys_enter_nanosleep")
138
137
int test_ringbuf (void * ctx )
139
138
{
140
139
struct bpf_dynptr ptr ;
141
- struct sample * sample ;
140
+ struct ringbuf_sample * sample ;
142
141
143
142
if (bpf_get_current_pid_tgid () >> 32 != pid )
144
143
return 0 ;
@@ -567,3 +566,117 @@ int BPF_PROG(test_dynptr_skb_tp_btf, void *skb, void *location)
567
566
568
567
return 1 ;
569
568
}
569
+
570
+ static inline int bpf_memcmp (const char * a , const char * b , u32 size )
571
+ {
572
+ int i ;
573
+
574
+ bpf_for (i , 0 , size ) {
575
+ if (a [i ] != b [i ])
576
+ return a [i ] < b [i ] ? -1 : 1 ;
577
+ }
578
+ return 0 ;
579
+ }
580
+
581
+ SEC ("?tp/syscalls/sys_enter_nanosleep" )
582
+ int test_dynptr_copy (void * ctx )
583
+ {
584
+ char data [] = "hello there, world!!" ;
585
+ char buf [32 ] = {'\0' };
586
+ __u32 sz = sizeof (data );
587
+ struct bpf_dynptr src , dst ;
588
+
589
+ bpf_ringbuf_reserve_dynptr (& ringbuf , sz , 0 , & src );
590
+ bpf_ringbuf_reserve_dynptr (& ringbuf , sz , 0 , & dst );
591
+
592
+ /* Test basic case of copying contiguous memory backed dynptrs */
593
+ err = bpf_dynptr_write (& src , 0 , data , sz , 0 );
594
+ err = err ?: bpf_dynptr_copy (& dst , 0 , & src , 0 , sz );
595
+ err = err ?: bpf_dynptr_read (buf , sz , & dst , 0 , 0 );
596
+ err = err ?: bpf_memcmp (data , buf , sz );
597
+
598
+ /* Test that offsets are handled correctly */
599
+ err = err ?: bpf_dynptr_copy (& dst , 3 , & src , 5 , sz - 5 );
600
+ err = err ?: bpf_dynptr_read (buf , sz - 5 , & dst , 3 , 0 );
601
+ err = err ?: bpf_memcmp (data + 5 , buf , sz - 5 );
602
+
603
+ bpf_ringbuf_discard_dynptr (& src , 0 );
604
+ bpf_ringbuf_discard_dynptr (& dst , 0 );
605
+ return 0 ;
606
+ }
607
+
608
+ SEC ("xdp" )
609
+ int test_dynptr_copy_xdp (struct xdp_md * xdp )
610
+ {
611
+ struct bpf_dynptr ptr_buf , ptr_xdp ;
612
+ char data [] = "qwertyuiopasdfghjkl" ;
613
+ char buf [32 ] = {'\0' };
614
+ __u32 len = sizeof (data );
615
+ int i , chunks = 200 ;
616
+
617
+ /* ptr_xdp is backed by non-contiguous memory */
618
+ bpf_dynptr_from_xdp (xdp , 0 , & ptr_xdp );
619
+ bpf_ringbuf_reserve_dynptr (& ringbuf , len * chunks , 0 , & ptr_buf );
620
+
621
+ /* Destination dynptr is backed by non-contiguous memory */
622
+ bpf_for (i , 0 , chunks ) {
623
+ err = bpf_dynptr_write (& ptr_buf , i * len , data , len , 0 );
624
+ if (err )
625
+ goto out ;
626
+ }
627
+
628
+ err = bpf_dynptr_copy (& ptr_xdp , 0 , & ptr_buf , 0 , len * chunks );
629
+ if (err )
630
+ goto out ;
631
+
632
+ bpf_for (i , 0 , chunks ) {
633
+ __builtin_memset (buf , 0 , sizeof (buf ));
634
+ err = bpf_dynptr_read (& buf , len , & ptr_xdp , i * len , 0 );
635
+ if (err )
636
+ goto out ;
637
+ if (bpf_memcmp (data , buf , len ) != 0 )
638
+ goto out ;
639
+ }
640
+
641
+ /* Source dynptr is backed by non-contiguous memory */
642
+ __builtin_memset (buf , 0 , sizeof (buf ));
643
+ bpf_for (i , 0 , chunks ) {
644
+ err = bpf_dynptr_write (& ptr_buf , i * len , buf , len , 0 );
645
+ if (err )
646
+ goto out ;
647
+ }
648
+
649
+ err = bpf_dynptr_copy (& ptr_buf , 0 , & ptr_xdp , 0 , len * chunks );
650
+ if (err )
651
+ goto out ;
652
+
653
+ bpf_for (i , 0 , chunks ) {
654
+ __builtin_memset (buf , 0 , sizeof (buf ));
655
+ err = bpf_dynptr_read (& buf , len , & ptr_buf , i * len , 0 );
656
+ if (err )
657
+ goto out ;
658
+ if (bpf_memcmp (data , buf , len ) != 0 )
659
+ goto out ;
660
+ }
661
+
662
+ /* Both source and destination dynptrs are backed by non-contiguous memory */
663
+ err = bpf_dynptr_copy (& ptr_xdp , 2 , & ptr_xdp , len , len * (chunks - 1 ));
664
+ if (err )
665
+ goto out ;
666
+
667
+ bpf_for (i , 0 , chunks - 1 ) {
668
+ __builtin_memset (buf , 0 , sizeof (buf ));
669
+ err = bpf_dynptr_read (& buf , len , & ptr_xdp , 2 + i * len , 0 );
670
+ if (err )
671
+ goto out ;
672
+ if (bpf_memcmp (data , buf , len ) != 0 )
673
+ goto out ;
674
+ }
675
+
676
+ if (bpf_dynptr_copy (& ptr_xdp , 2000 , & ptr_xdp , 0 , len * chunks ) != - E2BIG )
677
+ err = 1 ;
678
+
679
+ out :
680
+ bpf_ringbuf_discard_dynptr (& ptr_buf , 0 );
681
+ return XDP_DROP ;
682
+ }
0 commit comments