@@ -691,123 +691,88 @@ static int32_t load_bpf_file(struct bpf_engine *handle) {
691691 struct bpf_map_data maps [BPF_MAPS_MAX ];
692692 struct utsname osname ;
693693 int32_t res = SCAP_FAILURE ;
694- bool got_api_version = false;
695- bool got_schema_version = false;
696694
697695 if (uname (& osname )) {
698696 return scap_errprintf (handle -> m_lasterr , errno , "can't call uname()" );
699697 }
700698
701- if (elf_version (EV_CURRENT ) == EV_NONE ) {
702- return scap_errprintf (handle -> m_lasterr , 0 , "invalid ELF version" );
699+ // This should be already initialized when we load the API versions
700+ if (handle -> elf == NULL ) {
701+ return scap_errprintf (handle -> m_lasterr , errno , "ELF file not loaded" );
703702 }
704703
705- if (!handle -> elf ) {
706- handle -> program_fd = open (handle -> m_filepath , O_RDONLY , 0 );
707- if (handle -> program_fd < 0 ) {
708- return scap_errprintf (handle -> m_lasterr ,
709- 0 ,
710- "can't open BPF probe '%s'" ,
711- handle -> m_filepath );
712- }
713-
714- handle -> elf = elf_begin (handle -> program_fd , ELF_C_READ_MMAP_PRIVATE , NULL );
715- if (!handle -> elf ) {
716- scap_errprintf (handle -> m_lasterr , 0 , "can't read ELF format" );
717- goto end ;
718- }
704+ if (gelf_getehdr (handle -> elf , & handle -> ehdr ) != & handle -> ehdr ) {
705+ scap_errprintf (handle -> m_lasterr , 0 , "can't read ELF header" );
706+ goto end ;
707+ }
719708
720- if ( gelf_getehdr ( handle -> elf , & handle -> ehdr ) != & handle -> ehdr ) {
721- scap_errprintf ( handle -> m_lasterr , 0 , "can't read ELF header" );
722- goto end ;
709+ for ( j = 0 ; j < handle -> ehdr . e_shnum ; ++ j ) {
710+ if ( get_elf_section ( handle -> elf , j , & handle -> ehdr , & shname , & shdr , & data ) != SCAP_SUCCESS ) {
711+ continue ;
723712 }
724713
725- for (j = 0 ; j < handle -> ehdr .e_shnum ; ++ j ) {
726- if (get_elf_section (handle -> elf , j , & handle -> ehdr , & shname , & shdr , & data ) !=
727- SCAP_SUCCESS ) {
728- continue ;
729- }
730-
731- if (strcmp (shname , "maps" ) == 0 ) {
732- maps_shndx = j ;
733- } else if (shdr .sh_type == SHT_SYMTAB ) {
734- strtabidx = shdr .sh_link ;
735- symbols = data ;
736- } else if (strcmp (shname , "kernel_version" ) == 0 ) {
737- if (strcmp (osname .release , data -> d_buf )) {
738- snprintf (handle -> m_lasterr ,
739- SCAP_LASTERR_SIZE ,
740- "BPF probe is compiled for %s, but running version is %s" ,
741- (char * )data -> d_buf ,
742- osname .release );
743- goto end ;
744- }
745- } else if (strcmp (shname , "api_version" ) == 0 ) {
746- got_api_version = true;
747- memcpy (& handle -> m_api_version , data -> d_buf , sizeof (handle -> m_api_version ));
748- } else if (strcmp (shname , "schema_version" ) == 0 ) {
749- got_schema_version = true;
750- memcpy (& handle -> m_schema_version , data -> d_buf , sizeof (handle -> m_schema_version ));
751- } else if (strcmp (shname , "license" ) == 0 ) {
752- license = data -> d_buf ;
753- snprintf (handle -> m_lasterr , SCAP_LASTERR_SIZE , "BPF probe license is %s" , license );
714+ if (strcmp (shname , "maps" ) == 0 ) {
715+ maps_shndx = j ;
716+ } else if (shdr .sh_type == SHT_SYMTAB ) {
717+ strtabidx = shdr .sh_link ;
718+ symbols = data ;
719+ } else if (strcmp (shname , "kernel_version" ) == 0 ) {
720+ if (strcmp (osname .release , data -> d_buf )) {
721+ snprintf (handle -> m_lasterr ,
722+ SCAP_LASTERR_SIZE ,
723+ "BPF probe is compiled for %s, but running version is %s" ,
724+ (char * )data -> d_buf ,
725+ osname .release );
726+ goto end ;
754727 }
728+ } else if (strcmp (shname , "license" ) == 0 ) {
729+ license = data -> d_buf ;
730+ snprintf (handle -> m_lasterr , SCAP_LASTERR_SIZE , "BPF probe license is %s" , license );
755731 }
732+ }
756733
757- if (!got_api_version ) {
758- snprintf (handle -> m_lasterr , SCAP_LASTERR_SIZE , "missing api_version section" );
759- goto end ;
760- }
734+ if (!symbols ) {
735+ snprintf (handle -> m_lasterr , SCAP_LASTERR_SIZE , "missing SHT_SYMTAB section" );
736+ goto end ;
737+ }
761738
762- if (!got_schema_version ) {
763- snprintf (handle -> m_lasterr , SCAP_LASTERR_SIZE , "missing schema_version section" );
739+ if (maps_shndx ) {
740+ if (load_elf_maps_section (handle ,
741+ maps ,
742+ maps_shndx ,
743+ handle -> elf ,
744+ symbols ,
745+ strtabidx ,
746+ & nr_maps ) != SCAP_SUCCESS ) {
764747 goto end ;
765748 }
766749
767- if (!symbols ) {
768- snprintf (handle -> m_lasterr , SCAP_LASTERR_SIZE , "missing SHT_SYMTAB section" );
750+ if (load_maps (handle , maps , nr_maps ) != SCAP_SUCCESS ) {
769751 goto end ;
770752 }
753+ }
771754
772- if (maps_shndx ) {
773- if (load_elf_maps_section (handle ,
774- maps ,
775- maps_shndx ,
776- handle -> elf ,
777- symbols ,
778- strtabidx ,
779- & nr_maps ) != SCAP_SUCCESS ) {
780- goto end ;
781- }
782-
783- if (load_maps (handle , maps , nr_maps ) != SCAP_SUCCESS ) {
784- goto end ;
785- }
755+ for (j = 0 ; j < handle -> ehdr .e_shnum ; ++ j ) {
756+ if (get_elf_section (handle -> elf , j , & handle -> ehdr , & shname , & shdr , & data ) != SCAP_SUCCESS ) {
757+ continue ;
786758 }
787759
788- for (j = 0 ; j < handle -> ehdr .e_shnum ; ++ j ) {
789- if (get_elf_section (handle -> elf , j , & handle -> ehdr , & shname , & shdr , & data ) !=
790- SCAP_SUCCESS ) {
760+ if (shdr .sh_type == SHT_REL ) {
761+ struct bpf_insn * insns ;
762+
763+ if (get_elf_section (handle -> elf ,
764+ shdr .sh_info ,
765+ & handle -> ehdr ,
766+ & shname_prog ,
767+ & shdr_prog ,
768+ & data_prog ) != SCAP_SUCCESS ) {
791769 continue ;
792770 }
793771
794- if (shdr .sh_type == SHT_REL ) {
795- struct bpf_insn * insns ;
772+ insns = (struct bpf_insn * )data_prog -> d_buf ;
796773
797- if (get_elf_section (handle -> elf ,
798- shdr .sh_info ,
799- & handle -> ehdr ,
800- & shname_prog ,
801- & shdr_prog ,
802- & data_prog ) != SCAP_SUCCESS ) {
803- continue ;
804- }
805-
806- insns = (struct bpf_insn * )data_prog -> d_buf ;
807-
808- if (parse_relocations (handle , data , symbols , & shdr , insns , maps , nr_maps )) {
809- continue ;
810- }
774+ if (parse_relocations (handle , data , symbols , & shdr , insns , maps , nr_maps )) {
775+ continue ;
811776 }
812777 }
813778 }
@@ -1478,22 +1443,13 @@ static int32_t set_default_settings(struct bpf_engine *handle) {
14781443 return SCAP_SUCCESS ;
14791444}
14801445
1481- int32_t scap_bpf_load (struct bpf_engine * handle , const char * bpf_probe , scap_open_args * oargs ) {
1482- struct scap_bpf_engine_params * bpf_args = oargs -> engine_params ;
1483-
1446+ int32_t scap_bpf_load (struct bpf_engine * handle , unsigned long buffer_bytes_dim ) {
14841447 if (set_runtime_params (handle ) != SCAP_SUCCESS ) {
14851448 return SCAP_FAILURE ;
14861449 }
14871450
14881451 handle -> m_bpf_prog_array_map_idx = -1 ;
14891452
1490- if (!bpf_probe ) {
1491- ASSERT (false);
1492- return SCAP_FAILURE ;
1493- }
1494-
1495- snprintf (handle -> m_filepath , PATH_MAX , "%s" , bpf_probe );
1496-
14971453 if (load_bpf_file (handle ) != SCAP_SUCCESS ) {
14981454 return SCAP_FAILURE ;
14991455 }
@@ -1606,9 +1562,8 @@ int32_t scap_bpf_load(struct bpf_engine *handle, const char *bpf_probe, scap_ope
16061562 //
16071563 // Map the ring buffer
16081564 //
1609- dev -> m_buffer =
1610- perf_event_mmap (handle , pmu_fd , & dev -> m_mmap_size , bpf_args -> buffer_bytes_dim );
1611- dev -> m_buffer_size = bpf_args -> buffer_bytes_dim ;
1565+ dev -> m_buffer = perf_event_mmap (handle , pmu_fd , & dev -> m_mmap_size , buffer_bytes_dim );
1566+ dev -> m_buffer_size = buffer_bytes_dim ;
16121567 if (dev -> m_buffer == MAP_FAILED ) {
16131568 return scap_errprintf (handle -> m_lasterr ,
16141569 errno ,
@@ -1995,18 +1950,131 @@ static int32_t configure(struct scap_engine_handle engine,
19951950 }
19961951}
19971952
1953+ static int32_t load_api_versions (struct bpf_engine * handle ) {
1954+ GElf_Shdr shdr ;
1955+ Elf_Data * data ;
1956+ char * shname ;
1957+
1958+ if (elf_version (EV_CURRENT ) == EV_NONE ) {
1959+ return scap_errprintf (handle -> m_lasterr , 0 , "invalid ELF version" );
1960+ }
1961+
1962+ // This should be the first time in which we load the BPF probe.
1963+ if (handle -> elf != NULL ) {
1964+ return scap_errprintf (handle -> m_lasterr , 0 , "ELF already loaded but it shouldn't" );
1965+ }
1966+
1967+ handle -> program_fd = open (handle -> m_filepath , O_RDONLY , 0 );
1968+ if (handle -> program_fd < 0 ) {
1969+ return scap_errprintf (handle -> m_lasterr ,
1970+ 0 ,
1971+ "can't open BPF probe '%s'" ,
1972+ handle -> m_filepath );
1973+ }
1974+
1975+ handle -> elf = elf_begin (handle -> program_fd , ELF_C_READ_MMAP_PRIVATE , NULL );
1976+ if (!handle -> elf ) {
1977+ close (handle -> program_fd );
1978+ return scap_errprintf (handle -> m_lasterr , 0 , "can't read ELF format" );
1979+ }
1980+
1981+ if (gelf_getehdr (handle -> elf , & handle -> ehdr ) != & handle -> ehdr ) {
1982+ scap_errprintf (handle -> m_lasterr , 0 , "can't read ELF header" );
1983+ goto end ;
1984+ }
1985+
1986+ for (int j = 0 ; j < handle -> ehdr .e_shnum ; ++ j ) {
1987+ if (get_elf_section (handle -> elf , j , & handle -> ehdr , & shname , & shdr , & data ) != SCAP_SUCCESS ) {
1988+ continue ;
1989+ }
1990+
1991+ if (handle -> m_api_version != 0 && handle -> m_schema_version != 0 ) {
1992+ break ;
1993+ }
1994+
1995+ if (strncmp (shname , "api_version" , strlen ("api_version" )) == 0 ) {
1996+ memcpy (& handle -> m_api_version , data -> d_buf , sizeof (handle -> m_api_version ));
1997+ } else if (strncmp (shname , "schema_version" , strlen ("schema_version" )) == 0 ) {
1998+ memcpy (& handle -> m_schema_version , data -> d_buf , sizeof (handle -> m_schema_version ));
1999+ }
2000+ }
2001+
2002+ if (handle -> m_api_version == 0 ) {
2003+ snprintf (handle -> m_lasterr , SCAP_LASTERR_SIZE , "missing api_version section" );
2004+ goto end ;
2005+ }
2006+
2007+ if (handle -> m_schema_version == 0 ) {
2008+ snprintf (handle -> m_lasterr , SCAP_LASTERR_SIZE , "missing schema_version section" );
2009+ goto end ;
2010+ }
2011+ return SCAP_SUCCESS ;
2012+
2013+ end :
2014+ elf_end (handle -> elf );
2015+ close (handle -> program_fd );
2016+ return SCAP_FAILURE ;
2017+ }
2018+
2019+ int32_t check_schema_version_compatibility (uint64_t curr , char * error ) {
2020+ unsigned long driver_major = PPM_API_VERSION_MAJOR (curr );
2021+ unsigned long driver_minor = PPM_API_VERSION_MINOR (curr );
2022+ unsigned long driver_patch = PPM_API_VERSION_PATCH (curr );
2023+ unsigned long required_major = PPM_API_VERSION_MAJOR (SCAP_MINIMUM_DRIVER_SCHEMA_VERSION );
2024+ unsigned long required_minor = PPM_API_VERSION_MINOR (SCAP_MINIMUM_DRIVER_SCHEMA_VERSION );
2025+ unsigned long required_patch = PPM_API_VERSION_PATCH (SCAP_MINIMUM_DRIVER_SCHEMA_VERSION );
2026+ if (driver_major != required_major ) {
2027+ return scap_errprintf (error ,
2028+ 0 ,
2029+ "Scap and the legacy ebpf driver should have the same MAJOR version. "
2030+ "Ebpf MAJOR '%lu' != Scap MAJOR '%lu'" ,
2031+ driver_major ,
2032+ required_major );
2033+ }
2034+
2035+ if (driver_minor != required_minor ) {
2036+ return scap_errprintf (error ,
2037+ 0 ,
2038+ "Scap and the legacy ebpf driver should have the same MINOR version. "
2039+ "Ebpf MINOR '%lu' != Scap MINOR '%lu'" ,
2040+ driver_minor ,
2041+ required_minor );
2042+ }
2043+
2044+ if (driver_patch < required_patch ) {
2045+ return scap_errprintf (error ,
2046+ 0 ,
2047+ "The legacy ebpf driver should have a PATCH version >= Scap. "
2048+ "Ebpf PATCH '%lu' < Scap PATCH '%lu'" ,
2049+ driver_patch ,
2050+ required_patch );
2051+ }
2052+ return SCAP_SUCCESS ;
2053+ }
2054+
19982055static int32_t init (scap_t * handle , scap_open_args * oargs ) {
1999- int32_t rc = 0 ;
2000- char bpf_probe_buf [SCAP_MAX_PATH_SIZE ] = {0 };
20012056 struct scap_engine_handle engine = handle -> m_engine ;
20022057 struct scap_bpf_engine_params * params = oargs -> engine_params ;
2003- strlcpy (bpf_probe_buf , params -> bpf_probe , SCAP_MAX_PATH_SIZE );
2058+ strlcpy (HANDLE ( engine ) -> m_filepath , params -> bpf_probe , SCAP_MAX_PATH_SIZE );
20042059
20052060 if (check_buffer_bytes_dim (HANDLE (engine )-> m_lasterr , params -> buffer_bytes_dim ) !=
20062061 SCAP_SUCCESS ) {
20072062 return SCAP_FAILURE ;
20082063 }
20092064
2065+ // Load the API and schema versions from the ELF file.
2066+ if (load_api_versions (HANDLE (engine )) != SCAP_SUCCESS ) {
2067+ return SCAP_FAILURE ;
2068+ }
2069+
2070+ // Unless we refactor our architecture the legacy ebpf SCHEMA_VERSION is not semver compliant.
2071+ // For this reason we enforce a specific check here.
2072+ // See https://github.com/falcosecurity/libs/issues/1283
2073+ if (check_schema_version_compatibility (HANDLE (engine )-> m_schema_version ,
2074+ HANDLE (engine )-> m_lasterr ) != SCAP_SUCCESS ) {
2075+ return SCAP_FAILURE ;
2076+ }
2077+
20102078 //
20112079 // Find out how many devices we have to open, which equals to the number of online CPUs
20122080 //
@@ -2028,13 +2096,13 @@ static int32_t init(scap_t *handle, scap_open_args *oargs) {
20282096 "cannot obtain the number of online CPUs from '_SC_NPROCESSORS_ONLN'" );
20292097 }
20302098
2031- rc = devset_init (& HANDLE (engine )-> m_dev_set , num_devs , HANDLE (engine )-> m_lasterr );
2099+ int32_t rc = devset_init (& HANDLE (engine )-> m_dev_set , num_devs , HANDLE (engine )-> m_lasterr );
20322100 if (rc != SCAP_SUCCESS ) {
20332101 return rc ;
20342102 }
20352103
20362104 /* Here we need to load maps and progs but we shouldn't attach tracepoints */
2037- rc = scap_bpf_load (engine .m_handle , bpf_probe_buf , oargs );
2105+ rc = scap_bpf_load (engine .m_handle , params -> buffer_bytes_dim );
20382106 if (rc != SCAP_SUCCESS ) {
20392107 return rc ;
20402108 }
0 commit comments