@@ -18,6 +18,8 @@ struct bpf_struct_ops_value {
1818 char data [] ____cacheline_aligned_in_smp ;
1919};
2020
21+ #define MAX_TRAMP_IMAGE_PAGES 8
22+
2123struct bpf_struct_ops_map {
2224 struct bpf_map map ;
2325 struct rcu_head rcu ;
@@ -30,12 +32,11 @@ struct bpf_struct_ops_map {
3032 */
3133 struct bpf_link * * links ;
3234 u32 links_cnt ;
33- /* image is a page that has all the trampolines
35+ u32 image_pages_cnt ;
36+ /* image_pages is an array of pages that has all the trampolines
3437 * that stores the func args before calling the bpf_prog.
35- * A PAGE_SIZE "image" is enough to store all trampoline for
36- * "links[]".
3738 */
38- void * image ;
39+ void * image_pages [ MAX_TRAMP_IMAGE_PAGES ] ;
3940 /* The owner moduler's btf. */
4041 struct btf * btf ;
4142 /* uvalue->data stores the kernel struct
@@ -116,6 +117,31 @@ static bool is_valid_value_type(struct btf *btf, s32 value_id,
116117 return true;
117118}
118119
120+ static void * bpf_struct_ops_image_alloc (void )
121+ {
122+ void * image ;
123+ int err ;
124+
125+ err = bpf_jit_charge_modmem (PAGE_SIZE );
126+ if (err )
127+ return ERR_PTR (err );
128+ image = arch_alloc_bpf_trampoline (PAGE_SIZE );
129+ if (!image ) {
130+ bpf_jit_uncharge_modmem (PAGE_SIZE );
131+ return ERR_PTR (- ENOMEM );
132+ }
133+
134+ return image ;
135+ }
136+
137+ void bpf_struct_ops_image_free (void * image )
138+ {
139+ if (image ) {
140+ arch_free_bpf_trampoline (image , PAGE_SIZE );
141+ bpf_jit_uncharge_modmem (PAGE_SIZE );
142+ }
143+ }
144+
119145#define MAYBE_NULL_SUFFIX "__nullable"
120146#define MAX_STUB_NAME 128
121147
@@ -461,6 +487,15 @@ static void bpf_struct_ops_map_put_progs(struct bpf_struct_ops_map *st_map)
461487 }
462488}
463489
490+ static void bpf_struct_ops_map_free_image (struct bpf_struct_ops_map * st_map )
491+ {
492+ int i ;
493+
494+ for (i = 0 ; i < st_map -> image_pages_cnt ; i ++ )
495+ bpf_struct_ops_image_free (st_map -> image_pages [i ]);
496+ st_map -> image_pages_cnt = 0 ;
497+ }
498+
464499static int check_zero_holes (const struct btf * btf , const struct btf_type * t , void * data )
465500{
466501 const struct btf_member * member ;
@@ -506,9 +541,12 @@ const struct bpf_link_ops bpf_struct_ops_link_lops = {
506541int bpf_struct_ops_prepare_trampoline (struct bpf_tramp_links * tlinks ,
507542 struct bpf_tramp_link * link ,
508543 const struct btf_func_model * model ,
509- void * stub_func , void * image , void * image_end )
544+ void * stub_func ,
545+ void * * _image , u32 * _image_off ,
546+ bool allow_alloc )
510547{
511- u32 flags = BPF_TRAMP_F_INDIRECT ;
548+ u32 image_off = * _image_off , flags = BPF_TRAMP_F_INDIRECT ;
549+ void * image = * _image ;
512550 int size ;
513551
514552 tlinks [BPF_TRAMP_FENTRY ].links [0 ] = link ;
@@ -518,12 +556,32 @@ int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_links *tlinks,
518556 flags |= BPF_TRAMP_F_RET_FENTRY_RET ;
519557
520558 size = arch_bpf_trampoline_size (model , flags , tlinks , NULL );
521- if (size < 0 )
522- return size ;
523- if (size > (unsigned long )image_end - (unsigned long )image )
524- return - E2BIG ;
525- return arch_prepare_bpf_trampoline (NULL , image , image_end ,
559+ if (size <= 0 )
560+ return size ? : - EFAULT ;
561+
562+ /* Allocate image buffer if necessary */
563+ if (!image || size > PAGE_SIZE - image_off ) {
564+ if (!allow_alloc )
565+ return - E2BIG ;
566+
567+ image = bpf_struct_ops_image_alloc ();
568+ if (IS_ERR (image ))
569+ return PTR_ERR (image );
570+ image_off = 0 ;
571+ }
572+
573+ size = arch_prepare_bpf_trampoline (NULL , image + image_off ,
574+ image + PAGE_SIZE ,
526575 model , flags , tlinks , stub_func );
576+ if (size <= 0 ) {
577+ if (image != * _image )
578+ bpf_struct_ops_image_free (image );
579+ return size ? : - EFAULT ;
580+ }
581+
582+ * _image = image ;
583+ * _image_off = image_off + size ;
584+ return 0 ;
527585}
528586
529587static long bpf_struct_ops_map_update_elem (struct bpf_map * map , void * key ,
@@ -539,8 +597,8 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
539597 struct bpf_tramp_links * tlinks ;
540598 void * udata , * kdata ;
541599 int prog_fd , err ;
542- void * image , * image_end ;
543- u32 i ;
600+ u32 i , trampoline_start , image_off = 0 ;
601+ void * cur_image = NULL , * image = NULL ;
544602
545603 if (flags )
546604 return - EINVAL ;
@@ -578,8 +636,6 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
578636
579637 udata = & uvalue -> data ;
580638 kdata = & kvalue -> data ;
581- image = st_map -> image ;
582- image_end = st_map -> image + PAGE_SIZE ;
583639
584640 module_type = btf_type_by_id (btf_vmlinux , st_ops_ids [IDX_MODULE_ID ]);
585641 for_each_member (i , t , member ) {
@@ -658,28 +714,39 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
658714 & bpf_struct_ops_link_lops , prog );
659715 st_map -> links [i ] = & link -> link ;
660716
717+ trampoline_start = image_off ;
661718 err = bpf_struct_ops_prepare_trampoline (tlinks , link ,
662- & st_ops -> func_models [i ],
663- * (void * * )(st_ops -> cfi_stubs + moff ),
664- image , image_end );
719+ & st_ops -> func_models [i ],
720+ * (void * * )(st_ops -> cfi_stubs + moff ),
721+ & image , & image_off ,
722+ st_map -> image_pages_cnt < MAX_TRAMP_IMAGE_PAGES );
723+ if (err )
724+ goto reset_unlock ;
725+
726+ if (cur_image != image ) {
727+ st_map -> image_pages [st_map -> image_pages_cnt ++ ] = image ;
728+ cur_image = image ;
729+ trampoline_start = 0 ;
730+ }
665731 if (err < 0 )
666732 goto reset_unlock ;
667733
668- * (void * * )(kdata + moff ) = image + cfi_get_offset ();
669- image += err ;
734+ * (void * * )(kdata + moff ) = image + trampoline_start + cfi_get_offset ();
670735
671736 /* put prog_id to udata */
672737 * (unsigned long * )(udata + moff ) = prog -> aux -> id ;
673738 }
674739
740+ if (st_ops -> validate ) {
741+ err = st_ops -> validate (kdata );
742+ if (err )
743+ goto reset_unlock ;
744+ }
745+ for (i = 0 ; i < st_map -> image_pages_cnt ; i ++ )
746+ arch_protect_bpf_trampoline (st_map -> image_pages [i ], PAGE_SIZE );
747+
675748 if (st_map -> map .map_flags & BPF_F_LINK ) {
676749 err = 0 ;
677- if (st_ops -> validate ) {
678- err = st_ops -> validate (kdata );
679- if (err )
680- goto reset_unlock ;
681- }
682- arch_protect_bpf_trampoline (st_map -> image , PAGE_SIZE );
683750 /* Let bpf_link handle registration & unregistration.
684751 *
685752 * Pair with smp_load_acquire() during lookup_elem().
@@ -688,7 +755,6 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
688755 goto unlock ;
689756 }
690757
691- arch_protect_bpf_trampoline (st_map -> image , PAGE_SIZE );
692758 err = st_ops -> reg (kdata );
693759 if (likely (!err )) {
694760 /* This refcnt increment on the map here after
@@ -711,9 +777,9 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
711777 * there was a race in registering the struct_ops (under the same name) to
712778 * a sub-system through different struct_ops's maps.
713779 */
714- arch_unprotect_bpf_trampoline (st_map -> image , PAGE_SIZE );
715780
716781reset_unlock :
782+ bpf_struct_ops_map_free_image (st_map );
717783 bpf_struct_ops_map_put_progs (st_map );
718784 memset (uvalue , 0 , map -> value_size );
719785 memset (kvalue , 0 , map -> value_size );
@@ -780,10 +846,7 @@ static void __bpf_struct_ops_map_free(struct bpf_map *map)
780846 if (st_map -> links )
781847 bpf_struct_ops_map_put_progs (st_map );
782848 bpf_map_area_free (st_map -> links );
783- if (st_map -> image ) {
784- arch_free_bpf_trampoline (st_map -> image , PAGE_SIZE );
785- bpf_jit_uncharge_modmem (PAGE_SIZE );
786- }
849+ bpf_struct_ops_map_free_image (st_map );
787850 bpf_map_area_free (st_map -> uvalue );
788851 bpf_map_area_free (st_map );
789852}
@@ -893,20 +956,6 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr)
893956 st_map -> st_ops_desc = st_ops_desc ;
894957 map = & st_map -> map ;
895958
896- ret = bpf_jit_charge_modmem (PAGE_SIZE );
897- if (ret )
898- goto errout_free ;
899-
900- st_map -> image = arch_alloc_bpf_trampoline (PAGE_SIZE );
901- if (!st_map -> image ) {
902- /* __bpf_struct_ops_map_free() uses st_map->image as flag
903- * for "charged or not". In this case, we need to unchange
904- * here.
905- */
906- bpf_jit_uncharge_modmem (PAGE_SIZE );
907- ret = - ENOMEM ;
908- goto errout_free ;
909- }
910959 st_map -> uvalue = bpf_map_area_alloc (vt -> size , NUMA_NO_NODE );
911960 st_map -> links_cnt = btf_type_vlen (t );
912961 st_map -> links =
0 commit comments