@@ -23,7 +23,6 @@ struct bpf_struct_ops_value {
23
23
24
24
struct bpf_struct_ops_map {
25
25
struct bpf_map map ;
26
- struct rcu_head rcu ;
27
26
const struct bpf_struct_ops_desc * st_ops_desc ;
28
27
/* protect map_update */
29
28
struct mutex lock ;
@@ -32,7 +31,9 @@ struct bpf_struct_ops_map {
32
31
* (in kvalue.data).
33
32
*/
34
33
struct bpf_link * * links ;
35
- u32 links_cnt ;
34
+ /* ksyms for bpf trampolines */
35
+ struct bpf_ksym * * ksyms ;
36
+ u32 funcs_cnt ;
36
37
u32 image_pages_cnt ;
37
38
/* image_pages is an array of pages that has all the trampolines
38
39
* that stores the func args before calling the bpf_prog.
@@ -481,11 +482,11 @@ static void bpf_struct_ops_map_put_progs(struct bpf_struct_ops_map *st_map)
481
482
{
482
483
u32 i ;
483
484
484
- for (i = 0 ; i < st_map -> links_cnt ; i ++ ) {
485
- if (st_map -> links [i ]) {
486
- bpf_link_put ( st_map -> links [ i ]) ;
487
- st_map -> links [i ] = NULL ;
488
- }
485
+ for (i = 0 ; i < st_map -> funcs_cnt ; i ++ ) {
486
+ if (! st_map -> links [i ])
487
+ break ;
488
+ bpf_link_put ( st_map -> links [i ]) ;
489
+ st_map -> links [ i ] = NULL ;
489
490
}
490
491
}
491
492
@@ -586,6 +587,49 @@ int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_links *tlinks,
586
587
return 0 ;
587
588
}
588
589
590
+ static void bpf_struct_ops_ksym_init (const char * tname , const char * mname ,
591
+ void * image , unsigned int size ,
592
+ struct bpf_ksym * ksym )
593
+ {
594
+ snprintf (ksym -> name , KSYM_NAME_LEN , "bpf__%s_%s" , tname , mname );
595
+ INIT_LIST_HEAD_RCU (& ksym -> lnode );
596
+ bpf_image_ksym_init (image , size , ksym );
597
+ }
598
+
599
+ static void bpf_struct_ops_map_add_ksyms (struct bpf_struct_ops_map * st_map )
600
+ {
601
+ u32 i ;
602
+
603
+ for (i = 0 ; i < st_map -> funcs_cnt ; i ++ ) {
604
+ if (!st_map -> ksyms [i ])
605
+ break ;
606
+ bpf_image_ksym_add (st_map -> ksyms [i ]);
607
+ }
608
+ }
609
+
610
+ static void bpf_struct_ops_map_del_ksyms (struct bpf_struct_ops_map * st_map )
611
+ {
612
+ u32 i ;
613
+
614
+ for (i = 0 ; i < st_map -> funcs_cnt ; i ++ ) {
615
+ if (!st_map -> ksyms [i ])
616
+ break ;
617
+ bpf_image_ksym_del (st_map -> ksyms [i ]);
618
+ }
619
+ }
620
+
621
+ static void bpf_struct_ops_map_free_ksyms (struct bpf_struct_ops_map * st_map )
622
+ {
623
+ u32 i ;
624
+
625
+ for (i = 0 ; i < st_map -> funcs_cnt ; i ++ ) {
626
+ if (!st_map -> ksyms [i ])
627
+ break ;
628
+ kfree (st_map -> ksyms [i ]);
629
+ st_map -> ksyms [i ] = NULL ;
630
+ }
631
+ }
632
+
589
633
static long bpf_struct_ops_map_update_elem (struct bpf_map * map , void * key ,
590
634
void * value , u64 flags )
591
635
{
@@ -601,6 +645,9 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
601
645
int prog_fd , err ;
602
646
u32 i , trampoline_start , image_off = 0 ;
603
647
void * cur_image = NULL , * image = NULL ;
648
+ struct bpf_link * * plink ;
649
+ struct bpf_ksym * * pksym ;
650
+ const char * tname , * mname ;
604
651
605
652
if (flags )
606
653
return - EINVAL ;
@@ -639,14 +686,19 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
639
686
udata = & uvalue -> data ;
640
687
kdata = & kvalue -> data ;
641
688
689
+ plink = st_map -> links ;
690
+ pksym = st_map -> ksyms ;
691
+ tname = btf_name_by_offset (st_map -> btf , t -> name_off );
642
692
module_type = btf_type_by_id (btf_vmlinux , st_ops_ids [IDX_MODULE_ID ]);
643
693
for_each_member (i , t , member ) {
644
694
const struct btf_type * mtype , * ptype ;
645
695
struct bpf_prog * prog ;
646
696
struct bpf_tramp_link * link ;
697
+ struct bpf_ksym * ksym ;
647
698
u32 moff ;
648
699
649
700
moff = __btf_member_bit_offset (t , member ) / 8 ;
701
+ mname = btf_name_by_offset (st_map -> btf , member -> name_off );
650
702
ptype = btf_type_resolve_ptr (st_map -> btf , member -> type , NULL );
651
703
if (ptype == module_type ) {
652
704
if (* (void * * )(udata + moff ))
@@ -714,7 +766,14 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
714
766
}
715
767
bpf_link_init (& link -> link , BPF_LINK_TYPE_STRUCT_OPS ,
716
768
& bpf_struct_ops_link_lops , prog );
717
- st_map -> links [i ] = & link -> link ;
769
+ * plink ++ = & link -> link ;
770
+
771
+ ksym = kzalloc (sizeof (* ksym ), GFP_USER );
772
+ if (!ksym ) {
773
+ err = - ENOMEM ;
774
+ goto reset_unlock ;
775
+ }
776
+ * pksym ++ = ksym ;
718
777
719
778
trampoline_start = image_off ;
720
779
err = bpf_struct_ops_prepare_trampoline (tlinks , link ,
@@ -735,6 +794,12 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
735
794
736
795
/* put prog_id to udata */
737
796
* (unsigned long * )(udata + moff ) = prog -> aux -> id ;
797
+
798
+ /* init ksym for this trampoline */
799
+ bpf_struct_ops_ksym_init (tname , mname ,
800
+ image + trampoline_start ,
801
+ image_off - trampoline_start ,
802
+ ksym );
738
803
}
739
804
740
805
if (st_ops -> validate ) {
@@ -783,13 +848,16 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
783
848
*/
784
849
785
850
reset_unlock :
851
+ bpf_struct_ops_map_free_ksyms (st_map );
786
852
bpf_struct_ops_map_free_image (st_map );
787
853
bpf_struct_ops_map_put_progs (st_map );
788
854
memset (uvalue , 0 , map -> value_size );
789
855
memset (kvalue , 0 , map -> value_size );
790
856
unlock :
791
857
kfree (tlinks );
792
858
mutex_unlock (& st_map -> lock );
859
+ if (!err )
860
+ bpf_struct_ops_map_add_ksyms (st_map );
793
861
return err ;
794
862
}
795
863
@@ -849,7 +917,10 @@ static void __bpf_struct_ops_map_free(struct bpf_map *map)
849
917
850
918
if (st_map -> links )
851
919
bpf_struct_ops_map_put_progs (st_map );
920
+ if (st_map -> ksyms )
921
+ bpf_struct_ops_map_free_ksyms (st_map );
852
922
bpf_map_area_free (st_map -> links );
923
+ bpf_map_area_free (st_map -> ksyms );
853
924
bpf_struct_ops_map_free_image (st_map );
854
925
bpf_map_area_free (st_map -> uvalue );
855
926
bpf_map_area_free (st_map );
@@ -866,6 +937,8 @@ static void bpf_struct_ops_map_free(struct bpf_map *map)
866
937
if (btf_is_module (st_map -> btf ))
867
938
module_put (st_map -> st_ops_desc -> st_ops -> owner );
868
939
940
+ bpf_struct_ops_map_del_ksyms (st_map );
941
+
869
942
/* The struct_ops's function may switch to another struct_ops.
870
943
*
871
944
* For example, bpf_tcp_cc_x->init() may switch to
@@ -895,6 +968,19 @@ static int bpf_struct_ops_map_alloc_check(union bpf_attr *attr)
895
968
return 0 ;
896
969
}
897
970
971
+ static u32 count_func_ptrs (const struct btf * btf , const struct btf_type * t )
972
+ {
973
+ int i ;
974
+ u32 count ;
975
+ const struct btf_member * member ;
976
+
977
+ count = 0 ;
978
+ for_each_member (i , t , member )
979
+ if (btf_type_resolve_func_ptr (btf , member -> type , NULL ))
980
+ count ++ ;
981
+ return count ;
982
+ }
983
+
898
984
static struct bpf_map * bpf_struct_ops_map_alloc (union bpf_attr * attr )
899
985
{
900
986
const struct bpf_struct_ops_desc * st_ops_desc ;
@@ -961,11 +1047,15 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr)
961
1047
map = & st_map -> map ;
962
1048
963
1049
st_map -> uvalue = bpf_map_area_alloc (vt -> size , NUMA_NO_NODE );
964
- st_map -> links_cnt = btf_type_vlen ( t );
1050
+ st_map -> funcs_cnt = count_func_ptrs ( btf , t );
965
1051
st_map -> links =
966
- bpf_map_area_alloc (st_map -> links_cnt * sizeof (struct bpf_links * ),
1052
+ bpf_map_area_alloc (st_map -> funcs_cnt * sizeof (struct bpf_link * ),
1053
+ NUMA_NO_NODE );
1054
+
1055
+ st_map -> ksyms =
1056
+ bpf_map_area_alloc (st_map -> funcs_cnt * sizeof (struct bpf_ksym * ),
967
1057
NUMA_NO_NODE );
968
- if (!st_map -> uvalue || !st_map -> links ) {
1058
+ if (!st_map -> uvalue || !st_map -> links || ! st_map -> ksyms ) {
969
1059
ret = - ENOMEM ;
970
1060
goto errout_free ;
971
1061
}
@@ -994,7 +1084,8 @@ static u64 bpf_struct_ops_map_mem_usage(const struct bpf_map *map)
994
1084
usage = sizeof (* st_map ) +
995
1085
vt -> size - sizeof (struct bpf_struct_ops_value );
996
1086
usage += vt -> size ;
997
- usage += btf_type_vlen (vt ) * sizeof (struct bpf_links * );
1087
+ usage += st_map -> funcs_cnt * sizeof (struct bpf_link * );
1088
+ usage += st_map -> funcs_cnt * sizeof (struct bpf_ksym * );
998
1089
usage += PAGE_SIZE ;
999
1090
return usage ;
1000
1091
}
0 commit comments