@@ -23,7 +23,6 @@ struct bpf_struct_ops_value {
2323
2424struct bpf_struct_ops_map {
2525 struct bpf_map map ;
26- struct rcu_head rcu ;
2726 const struct bpf_struct_ops_desc * st_ops_desc ;
2827 /* protect map_update */
2928 struct mutex lock ;
@@ -32,7 +31,9 @@ struct bpf_struct_ops_map {
3231 * (in kvalue.data).
3332 */
3433 struct bpf_link * * links ;
35- u32 links_cnt ;
34+ /* ksyms for bpf trampolines */
35+ struct bpf_ksym * * ksyms ;
36+ u32 funcs_cnt ;
3637 u32 image_pages_cnt ;
3738 /* image_pages is an array of pages that has all the trampolines
3839 * 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)
481482{
482483 u32 i ;
483484
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 ;
489490 }
490491}
491492
@@ -586,6 +587,49 @@ int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_links *tlinks,
586587 return 0 ;
587588}
588589
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+
589633static long bpf_struct_ops_map_update_elem (struct bpf_map * map , void * key ,
590634 void * value , u64 flags )
591635{
@@ -601,6 +645,9 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
601645 int prog_fd , err ;
602646 u32 i , trampoline_start , image_off = 0 ;
603647 void * cur_image = NULL , * image = NULL ;
648+ struct bpf_link * * plink ;
649+ struct bpf_ksym * * pksym ;
650+ const char * tname , * mname ;
604651
605652 if (flags )
606653 return - EINVAL ;
@@ -639,14 +686,19 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
639686 udata = & uvalue -> data ;
640687 kdata = & kvalue -> data ;
641688
689+ plink = st_map -> links ;
690+ pksym = st_map -> ksyms ;
691+ tname = btf_name_by_offset (st_map -> btf , t -> name_off );
642692 module_type = btf_type_by_id (btf_vmlinux , st_ops_ids [IDX_MODULE_ID ]);
643693 for_each_member (i , t , member ) {
644694 const struct btf_type * mtype , * ptype ;
645695 struct bpf_prog * prog ;
646696 struct bpf_tramp_link * link ;
697+ struct bpf_ksym * ksym ;
647698 u32 moff ;
648699
649700 moff = __btf_member_bit_offset (t , member ) / 8 ;
701+ mname = btf_name_by_offset (st_map -> btf , member -> name_off );
650702 ptype = btf_type_resolve_ptr (st_map -> btf , member -> type , NULL );
651703 if (ptype == module_type ) {
652704 if (* (void * * )(udata + moff ))
@@ -714,7 +766,14 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
714766 }
715767 bpf_link_init (& link -> link , BPF_LINK_TYPE_STRUCT_OPS ,
716768 & 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 ;
718777
719778 trampoline_start = image_off ;
720779 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,
735794
736795 /* put prog_id to udata */
737796 * (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 );
738803 }
739804
740805 if (st_ops -> validate ) {
@@ -783,13 +848,16 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
783848 */
784849
785850reset_unlock :
851+ bpf_struct_ops_map_free_ksyms (st_map );
786852 bpf_struct_ops_map_free_image (st_map );
787853 bpf_struct_ops_map_put_progs (st_map );
788854 memset (uvalue , 0 , map -> value_size );
789855 memset (kvalue , 0 , map -> value_size );
790856unlock :
791857 kfree (tlinks );
792858 mutex_unlock (& st_map -> lock );
859+ if (!err )
860+ bpf_struct_ops_map_add_ksyms (st_map );
793861 return err ;
794862}
795863
@@ -849,7 +917,10 @@ static void __bpf_struct_ops_map_free(struct bpf_map *map)
849917
850918 if (st_map -> links )
851919 bpf_struct_ops_map_put_progs (st_map );
920+ if (st_map -> ksyms )
921+ bpf_struct_ops_map_free_ksyms (st_map );
852922 bpf_map_area_free (st_map -> links );
923+ bpf_map_area_free (st_map -> ksyms );
853924 bpf_struct_ops_map_free_image (st_map );
854925 bpf_map_area_free (st_map -> uvalue );
855926 bpf_map_area_free (st_map );
@@ -866,6 +937,8 @@ static void bpf_struct_ops_map_free(struct bpf_map *map)
866937 if (btf_is_module (st_map -> btf ))
867938 module_put (st_map -> st_ops_desc -> st_ops -> owner );
868939
940+ bpf_struct_ops_map_del_ksyms (st_map );
941+
869942 /* The struct_ops's function may switch to another struct_ops.
870943 *
871944 * 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)
895968 return 0 ;
896969}
897970
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+
898984static struct bpf_map * bpf_struct_ops_map_alloc (union bpf_attr * attr )
899985{
900986 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)
9611047 map = & st_map -> map ;
9621048
9631049 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 );
9651051 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 * ),
9671057 NUMA_NO_NODE );
968- if (!st_map -> uvalue || !st_map -> links ) {
1058+ if (!st_map -> uvalue || !st_map -> links || ! st_map -> ksyms ) {
9691059 ret = - ENOMEM ;
9701060 goto errout_free ;
9711061 }
@@ -994,7 +1084,8 @@ static u64 bpf_struct_ops_map_mem_usage(const struct bpf_map *map)
9941084 usage = sizeof (* st_map ) +
9951085 vt -> size - sizeof (struct bpf_struct_ops_value );
9961086 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 * );
9981089 usage += PAGE_SIZE ;
9991090 return usage ;
10001091}
0 commit comments