@@ -8,7 +8,7 @@ use std::{
8
8
} ;
9
9
10
10
use assert_matches:: assert_matches;
11
- use libc:: { ENOENT , ENOSPC } ;
11
+ use libc:: { E2BIG , EINVAL , ENOENT , ENOSPC } ;
12
12
use obj:: {
13
13
btf:: { BtfEnum64 , Enum64 } ,
14
14
generated:: bpf_stats_type,
@@ -736,6 +736,56 @@ pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> Result<crate::MockableFd, Syscall
736
736
} )
737
737
}
738
738
739
+ // This program is to test the availability of eBPF features.
740
+ // It is a simple program that returns immediately and should always pass the
741
+ // verifier regardless of the program type.
742
+ // The fields conforming an encoded basic instruction are stored in the following order:
743
+ // opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF.
744
+ // opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF.
745
+ // Multi-byte fields ('imm' and 'offset') are stored using endian order.
746
+ // https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding
747
+ const TEST_PROG : & [ u8 ] = & [
748
+ 0xb7 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // mov64 r0 = 0
749
+ 0x95 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // exit
750
+ ] ;
751
+
752
+ pub ( crate ) fn is_prog_type_supported ( kind : bpf_prog_type ) -> Result < bool , SyscallError > {
753
+ let mut attr = unsafe { mem:: zeroed :: < bpf_attr > ( ) } ;
754
+ let u = unsafe { & mut attr. __bindgen_anon_3 } ;
755
+ u. prog_type = kind as u32 ;
756
+ let mut name: [ c_char ; 16 ] = [ 0 ; 16 ] ;
757
+ let cstring = CString :: new ( "aya_prog_check" ) . unwrap ( ) ;
758
+ let name_bytes = cstring. to_bytes ( ) ;
759
+ let len = cmp:: min ( name. len ( ) , name_bytes. len ( ) ) ;
760
+ name[ ..len] . copy_from_slice ( unsafe {
761
+ slice:: from_raw_parts ( name_bytes. as_ptr ( ) as * const c_char , len)
762
+ } ) ;
763
+ u. prog_name = name;
764
+
765
+ let gpl = b"GPL\0 " ;
766
+ u. license = gpl. as_ptr ( ) as u64 ;
767
+
768
+ let insns = copy_instructions ( TEST_PROG ) . unwrap ( ) ;
769
+ u. insn_cnt = insns. len ( ) as u32 ;
770
+ u. insns = insns. as_ptr ( ) as u64 ;
771
+ u. prog_type = bpf_prog_type:: BPF_PROG_TYPE_SOCKET_FILTER as u32 ;
772
+
773
+ let res = bpf_prog_load ( & mut attr) ;
774
+ match res {
775
+ Ok ( _) => Ok ( true ) ,
776
+ Err ( ( _, e) ) => {
777
+ if e. raw_os_error ( ) == Some ( EINVAL ) || e. raw_os_error ( ) == Some ( E2BIG ) {
778
+ Ok ( false )
779
+ } else {
780
+ Err ( SyscallError {
781
+ call : "bpf_prog_load" ,
782
+ io_error : e,
783
+ } )
784
+ }
785
+ }
786
+ }
787
+ }
788
+
739
789
pub ( crate ) fn is_prog_name_supported ( ) -> bool {
740
790
let mut attr = unsafe { mem:: zeroed :: < bpf_attr > ( ) } ;
741
791
let u = unsafe { & mut attr. __bindgen_anon_3 } ;
@@ -748,20 +798,10 @@ pub(crate) fn is_prog_name_supported() -> bool {
748
798
} ) ;
749
799
u. prog_name = name;
750
800
751
- // The fields conforming an encoded basic instruction are stored in the following order:
752
- // opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF.
753
- // opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF.
754
- // Multi-byte fields ('imm' and 'offset') are stored using endian order.
755
- // https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding
756
- let prog: & [ u8 ] = & [
757
- 0xb7 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // mov64 r0 = 0
758
- 0x95 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // exit
759
- ] ;
760
-
761
801
let gpl = b"GPL\0 " ;
762
802
u. license = gpl. as_ptr ( ) as u64 ;
763
803
764
- let insns = copy_instructions ( prog ) . unwrap ( ) ;
804
+ let insns = copy_instructions ( TEST_PROG ) . unwrap ( ) ;
765
805
u. insn_cnt = insns. len ( ) as u32 ;
766
806
u. insns = insns. as_ptr ( ) as u64 ;
767
807
u. prog_type = bpf_prog_type:: BPF_PROG_TYPE_SOCKET_FILTER as u32 ;
@@ -776,11 +816,7 @@ pub(crate) fn is_info_map_ids_supported() -> bool {
776
816
777
817
u. prog_type = bpf_prog_type:: BPF_PROG_TYPE_SOCKET_FILTER as u32 ;
778
818
779
- let prog: & [ u8 ] = & [
780
- 0xb7 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // mov64 r0 = 0
781
- 0x95 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // exit
782
- ] ;
783
- let insns = copy_instructions ( prog) . unwrap ( ) ;
819
+ let insns = copy_instructions ( TEST_PROG ) . unwrap ( ) ;
784
820
u. insn_cnt = insns. len ( ) as u32 ;
785
821
u. insns = insns. as_ptr ( ) as u64 ;
786
822
@@ -804,11 +840,7 @@ pub(crate) fn is_info_gpl_compatible_supported() -> bool {
804
840
805
841
u. prog_type = bpf_prog_type:: BPF_PROG_TYPE_SOCKET_FILTER as u32 ;
806
842
807
- let prog: & [ u8 ] = & [
808
- 0xb7 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // mov64 r0 = 0
809
- 0x95 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // exit
810
- ] ;
811
- let insns = copy_instructions ( prog) . unwrap ( ) ;
843
+ let insns = copy_instructions ( TEST_PROG ) . unwrap ( ) ;
812
844
u. insn_cnt = insns. len ( ) as u32 ;
813
845
u. insns = insns. as_ptr ( ) as u64 ;
814
846
@@ -868,20 +900,10 @@ pub(crate) fn is_perf_link_supported() -> bool {
868
900
let mut attr = unsafe { mem:: zeroed :: < bpf_attr > ( ) } ;
869
901
let u = unsafe { & mut attr. __bindgen_anon_3 } ;
870
902
871
- // The fields conforming an encoded basic instruction are stored in the following order:
872
- // opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF.
873
- // opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF.
874
- // Multi-byte fields ('imm' and 'offset') are stored using endian order.
875
- // https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding
876
- let prog: & [ u8 ] = & [
877
- 0xb7 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // mov64 r0 = 0
878
- 0x95 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // exit
879
- ] ;
880
-
881
903
let gpl = b"GPL\0 " ;
882
904
u. license = gpl. as_ptr ( ) as u64 ;
883
905
884
- let insns = copy_instructions ( prog ) . unwrap ( ) ;
906
+ let insns = copy_instructions ( TEST_PROG ) . unwrap ( ) ;
885
907
u. insn_cnt = insns. len ( ) as u32 ;
886
908
u. insns = insns. as_ptr ( ) as u64 ;
887
909
u. prog_type = bpf_prog_type:: BPF_PROG_TYPE_TRACEPOINT as u32 ;
0 commit comments