@@ -595,6 +595,136 @@ struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type typ
595
595
}
596
596
EXPORT_SYMBOL (bpf_prog_get_type_path );
597
597
598
+ struct bpffs_btf_enums {
599
+ const struct btf * btf ;
600
+ const struct btf_type * cmd_t ;
601
+ const struct btf_type * map_t ;
602
+ const struct btf_type * prog_t ;
603
+ const struct btf_type * attach_t ;
604
+ };
605
+
606
+ static int find_bpffs_btf_enums (struct bpffs_btf_enums * info )
607
+ {
608
+ const struct btf * btf ;
609
+ const struct btf_type * t ;
610
+ const char * name ;
611
+ int i , n ;
612
+
613
+ memset (info , 0 , sizeof (* info ));
614
+
615
+ btf = bpf_get_btf_vmlinux ();
616
+ if (IS_ERR (btf ))
617
+ return PTR_ERR (btf );
618
+ if (!btf )
619
+ return - ENOENT ;
620
+
621
+ info -> btf = btf ;
622
+
623
+ for (i = 1 , n = btf_nr_types (btf ); i < n ; i ++ ) {
624
+ t = btf_type_by_id (btf , i );
625
+ if (!btf_type_is_enum (t ))
626
+ continue ;
627
+
628
+ name = btf_name_by_offset (btf , t -> name_off );
629
+ if (!name )
630
+ continue ;
631
+
632
+ if (strcmp (name , "bpf_cmd" ) == 0 )
633
+ info -> cmd_t = t ;
634
+ else if (strcmp (name , "bpf_map_type" ) == 0 )
635
+ info -> map_t = t ;
636
+ else if (strcmp (name , "bpf_prog_type" ) == 0 )
637
+ info -> prog_t = t ;
638
+ else if (strcmp (name , "bpf_attach_type" ) == 0 )
639
+ info -> attach_t = t ;
640
+ else
641
+ continue ;
642
+
643
+ if (info -> cmd_t && info -> map_t && info -> prog_t && info -> attach_t )
644
+ return 0 ;
645
+ }
646
+
647
+ return - ESRCH ;
648
+ }
649
+
650
+ static bool find_btf_enum_const (const struct btf * btf , const struct btf_type * enum_t ,
651
+ const char * prefix , const char * str , int * value )
652
+ {
653
+ const struct btf_enum * e ;
654
+ const char * name ;
655
+ int i , n , pfx_len = strlen (prefix );
656
+
657
+ * value = 0 ;
658
+
659
+ if (!btf || !enum_t )
660
+ return false;
661
+
662
+ for (i = 0 , n = btf_vlen (enum_t ); i < n ; i ++ ) {
663
+ e = & btf_enum (enum_t )[i ];
664
+
665
+ name = btf_name_by_offset (btf , e -> name_off );
666
+ if (!name || strncasecmp (name , prefix , pfx_len ) != 0 )
667
+ continue ;
668
+
669
+ /* match symbolic name case insensitive and ignoring prefix */
670
+ if (strcasecmp (name + pfx_len , str ) == 0 ) {
671
+ * value = e -> val ;
672
+ return true;
673
+ }
674
+ }
675
+
676
+ return false;
677
+ }
678
+
679
+ static void seq_print_delegate_opts (struct seq_file * m ,
680
+ const char * opt_name ,
681
+ const struct btf * btf ,
682
+ const struct btf_type * enum_t ,
683
+ const char * prefix ,
684
+ u64 delegate_msk , u64 any_msk )
685
+ {
686
+ const struct btf_enum * e ;
687
+ bool first = true;
688
+ const char * name ;
689
+ u64 msk ;
690
+ int i , n , pfx_len = strlen (prefix );
691
+
692
+ delegate_msk &= any_msk ; /* clear unknown bits */
693
+
694
+ if (delegate_msk == 0 )
695
+ return ;
696
+
697
+ seq_printf (m , ",%s" , opt_name );
698
+ if (delegate_msk == any_msk ) {
699
+ seq_printf (m , "=any" );
700
+ return ;
701
+ }
702
+
703
+ if (btf && enum_t ) {
704
+ for (i = 0 , n = btf_vlen (enum_t ); i < n ; i ++ ) {
705
+ e = & btf_enum (enum_t )[i ];
706
+ name = btf_name_by_offset (btf , e -> name_off );
707
+ if (!name || strncasecmp (name , prefix , pfx_len ) != 0 )
708
+ continue ;
709
+ msk = 1ULL << e -> val ;
710
+ if (delegate_msk & msk ) {
711
+ /* emit lower-case name without prefix */
712
+ seq_printf (m , "%c" , first ? '=' : ':' );
713
+ name += pfx_len ;
714
+ while (* name ) {
715
+ seq_printf (m , "%c" , tolower (* name ));
716
+ name ++ ;
717
+ }
718
+
719
+ delegate_msk &= ~msk ;
720
+ first = false;
721
+ }
722
+ }
723
+ }
724
+ if (delegate_msk )
725
+ seq_printf (m , "%c0x%llx" , first ? '=' : ':' , delegate_msk );
726
+ }
727
+
598
728
/*
599
729
* Display the mount options in /proc/mounts.
600
730
*/
@@ -614,29 +744,34 @@ static int bpf_show_options(struct seq_file *m, struct dentry *root)
614
744
if (mode != S_IRWXUGO )
615
745
seq_printf (m , ",mode=%o" , mode );
616
746
617
- mask = (1ULL << __MAX_BPF_CMD ) - 1 ;
618
- if ((opts -> delegate_cmds & mask ) == mask )
619
- seq_printf (m , ",delegate_cmds=any" );
620
- else if (opts -> delegate_cmds )
621
- seq_printf (m , ",delegate_cmds=0x%llx" , opts -> delegate_cmds );
622
-
623
- mask = (1ULL << __MAX_BPF_MAP_TYPE ) - 1 ;
624
- if ((opts -> delegate_maps & mask ) == mask )
625
- seq_printf (m , ",delegate_maps=any" );
626
- else if (opts -> delegate_maps )
627
- seq_printf (m , ",delegate_maps=0x%llx" , opts -> delegate_maps );
628
-
629
- mask = (1ULL << __MAX_BPF_PROG_TYPE ) - 1 ;
630
- if ((opts -> delegate_progs & mask ) == mask )
631
- seq_printf (m , ",delegate_progs=any" );
632
- else if (opts -> delegate_progs )
633
- seq_printf (m , ",delegate_progs=0x%llx" , opts -> delegate_progs );
634
-
635
- mask = (1ULL << __MAX_BPF_ATTACH_TYPE ) - 1 ;
636
- if ((opts -> delegate_attachs & mask ) == mask )
637
- seq_printf (m , ",delegate_attachs=any" );
638
- else if (opts -> delegate_attachs )
639
- seq_printf (m , ",delegate_attachs=0x%llx" , opts -> delegate_attachs );
747
+ if (opts -> delegate_cmds || opts -> delegate_maps ||
748
+ opts -> delegate_progs || opts -> delegate_attachs ) {
749
+ struct bpffs_btf_enums info ;
750
+
751
+ /* ignore errors, fallback to hex */
752
+ (void )find_bpffs_btf_enums (& info );
753
+
754
+ mask = (1ULL << __MAX_BPF_CMD ) - 1 ;
755
+ seq_print_delegate_opts (m , "delegate_cmds" ,
756
+ info .btf , info .cmd_t , "BPF_" ,
757
+ opts -> delegate_cmds , mask );
758
+
759
+ mask = (1ULL << __MAX_BPF_MAP_TYPE ) - 1 ;
760
+ seq_print_delegate_opts (m , "delegate_maps" ,
761
+ info .btf , info .map_t , "BPF_MAP_TYPE_" ,
762
+ opts -> delegate_maps , mask );
763
+
764
+ mask = (1ULL << __MAX_BPF_PROG_TYPE ) - 1 ;
765
+ seq_print_delegate_opts (m , "delegate_progs" ,
766
+ info .btf , info .prog_t , "BPF_PROG_TYPE_" ,
767
+ opts -> delegate_progs , mask );
768
+
769
+ mask = (1ULL << __MAX_BPF_ATTACH_TYPE ) - 1 ;
770
+ seq_print_delegate_opts (m , "delegate_attachs" ,
771
+ info .btf , info .attach_t , "BPF_" ,
772
+ opts -> delegate_attachs , mask );
773
+ }
774
+
640
775
return 0 ;
641
776
}
642
777
@@ -686,7 +821,6 @@ static int bpf_parse_param(struct fs_context *fc, struct fs_parameter *param)
686
821
kuid_t uid ;
687
822
kgid_t gid ;
688
823
int opt , err ;
689
- u64 msk ;
690
824
691
825
opt = fs_parse (fc , bpf_fs_parameters , param , & result );
692
826
if (opt < 0 ) {
@@ -741,24 +875,63 @@ static int bpf_parse_param(struct fs_context *fc, struct fs_parameter *param)
741
875
case OPT_DELEGATE_CMDS :
742
876
case OPT_DELEGATE_MAPS :
743
877
case OPT_DELEGATE_PROGS :
744
- case OPT_DELEGATE_ATTACHS :
745
- if (strcmp (param -> string , "any" ) == 0 ) {
746
- msk = ~0ULL ;
747
- } else {
748
- err = kstrtou64 (param -> string , 0 , & msk );
749
- if (err )
750
- return err ;
878
+ case OPT_DELEGATE_ATTACHS : {
879
+ struct bpffs_btf_enums info ;
880
+ const struct btf_type * enum_t ;
881
+ const char * enum_pfx ;
882
+ u64 * delegate_msk , msk = 0 ;
883
+ char * p ;
884
+ int val ;
885
+
886
+ /* ignore errors, fallback to hex */
887
+ (void )find_bpffs_btf_enums (& info );
888
+
889
+ switch (opt ) {
890
+ case OPT_DELEGATE_CMDS :
891
+ delegate_msk = & opts -> delegate_cmds ;
892
+ enum_t = info .cmd_t ;
893
+ enum_pfx = "BPF_" ;
894
+ break ;
895
+ case OPT_DELEGATE_MAPS :
896
+ delegate_msk = & opts -> delegate_maps ;
897
+ enum_t = info .map_t ;
898
+ enum_pfx = "BPF_MAP_TYPE_" ;
899
+ break ;
900
+ case OPT_DELEGATE_PROGS :
901
+ delegate_msk = & opts -> delegate_progs ;
902
+ enum_t = info .prog_t ;
903
+ enum_pfx = "BPF_PROG_TYPE_" ;
904
+ break ;
905
+ case OPT_DELEGATE_ATTACHS :
906
+ delegate_msk = & opts -> delegate_attachs ;
907
+ enum_t = info .attach_t ;
908
+ enum_pfx = "BPF_" ;
909
+ break ;
910
+ default :
911
+ return - EINVAL ;
751
912
}
913
+
914
+ while ((p = strsep (& param -> string , ":" ))) {
915
+ if (strcmp (p , "any" ) == 0 ) {
916
+ msk |= ~0ULL ;
917
+ } else if (find_btf_enum_const (info .btf , enum_t , enum_pfx , p , & val )) {
918
+ msk |= 1ULL << val ;
919
+ } else {
920
+ err = kstrtou64 (p , 0 , & msk );
921
+ if (err )
922
+ return err ;
923
+ }
924
+ }
925
+
752
926
/* Setting delegation mount options requires privileges */
753
927
if (msk && !capable (CAP_SYS_ADMIN ))
754
928
return - EPERM ;
755
- switch (opt ) {
756
- case OPT_DELEGATE_CMDS : opts -> delegate_cmds |= msk ; break ;
757
- case OPT_DELEGATE_MAPS : opts -> delegate_maps |= msk ; break ;
758
- case OPT_DELEGATE_PROGS : opts -> delegate_progs |= msk ; break ;
759
- case OPT_DELEGATE_ATTACHS : opts -> delegate_attachs |= msk ; break ;
760
- default : return - EINVAL ;
761
- }
929
+
930
+ * delegate_msk |= msk ;
931
+ break ;
932
+ }
933
+ default :
934
+ /* ignore unknown mount options */
762
935
break ;
763
936
}
764
937
0 commit comments