diff --git a/userspace/libscap/CMakeLists.txt b/userspace/libscap/CMakeLists.txt index 7dc010e754e..a441b5bea26 100644 --- a/userspace/libscap/CMakeLists.txt +++ b/userspace/libscap/CMakeLists.txt @@ -57,6 +57,7 @@ endif() list(APPEND targetfiles scap.c + scap_api_version.c scap_fds.c scap_savefile.c scap_platform.c diff --git a/userspace/libscap/engine/udig/scap_udig.c b/userspace/libscap/engine/udig/scap_udig.c index 8a77e8a5076..4d35813c74b 100644 --- a/userspace/libscap/engine/udig/scap_udig.c +++ b/userspace/libscap/engine/udig/scap_udig.c @@ -276,9 +276,8 @@ bool acquire_and_init_ring_status_buffer(struct scap_device *dev) return res; } -int32_t udig_begin_capture(struct scap_engine_handle engine, char *error) +int32_t udig_begin_capture(struct scap_device *dev, char *error) { - struct scap_device *dev = &engine.m_handle->m_dev_set.m_devs[0]; struct udig_ring_buffer_status* rbs = dev->m_bufstatus; if(rbs->m_capturing_pid != 0) @@ -311,7 +310,6 @@ int32_t udig_begin_capture(struct scap_engine_handle engine, char *error) if(acquire_and_init_ring_status_buffer(dev)) { - engine.m_handle->m_udig_capturing = true; return SCAP_SUCCESS; } else @@ -547,7 +545,20 @@ static int32_t init(scap_t* main_handle, scap_open_args* oargs) return rc; } - return scap_udig_alloc_dev(&handle->m_dev_set.m_devs[0], handle->m_lasterr); + rc = scap_udig_alloc_dev(&handle->m_dev_set.m_devs[0], handle->m_lasterr); + if(rc != SCAP_SUCCESS) + { + return rc; + } + + struct scap_device *dev = &handle->m_dev_set.m_devs[0]; + rc = udig_begin_capture(dev, handle->m_lasterr); + if(rc == SCAP_SUCCESS) + { + handle->m_udig_capturing = true; + } + + return rc; } static uint32_t get_n_devs(struct scap_engine_handle engine) diff --git a/userspace/libscap/scap-int.h b/userspace/libscap/scap-int.h index 72947942ccb..1d6e72c4cb4 100644 --- a/userspace/libscap/scap-int.h +++ b/userspace/libscap/scap-int.h @@ -49,7 +49,6 @@ struct scap struct scap_engine_handle m_engine; struct scap_platform *m_platform; - scap_mode_t m_mode; char m_lasterr[SCAP_LASTERR_SIZE]; uint64_t m_evtcnt; @@ -123,11 +122,6 @@ extern const struct syscall_evt_pair g_syscall_table[]; extern const struct ppm_event_info g_event_info[]; extern const struct ppm_event_entry g_ppm_events[]; -// -// udig stuff -// -int32_t udig_begin_capture(struct scap_engine_handle engine, char *error); - #ifdef __cplusplus } #endif diff --git a/userspace/libscap/scap.c b/userspace/libscap/scap.c index 7fce8b2885b..f9b66807b07 100644 --- a/userspace/libscap/scap.c +++ b/userspace/libscap/scap.c @@ -16,47 +16,33 @@ limitations under the License. */ #include -#include -#ifdef _WIN32 -#include -#else -#include -#include -#include -#include -#endif // _WIN32 #include "scap.h" #include "strerror.h" #include "strl.h" -#include "../../driver/ppm_ringbuffer.h" #include "scap-int.h" -#include "scap_engine_util.h" +#include "scap_api_version.h" #include "scap_platform.h" +#define SCAP_HANDLE_T void #include "scap_engines.h" #ifdef __linux__ #include "scap_linux_platform.h" #endif -//#define NDEBUG -#include - const char* scap_getlasterr(scap_t* handle) { return handle ? handle->m_lasterr : "null scap handle"; } -#if defined(HAS_ENGINE_KMOD) || defined(HAS_ENGINE_BPF) || defined(HAS_ENGINE_MODERN_BPF) -int32_t scap_init_live_int(scap_t* handle, scap_open_args* oargs, const struct scap_vtable* vtable, struct scap_platform* platform) +int32_t scap_init_int(scap_t* handle, scap_open_args* oargs, const struct scap_vtable* vtable, struct scap_platform* platform) { int32_t rc; // // Preliminary initializations // - handle->m_mode = SCAP_MODE_LIVE; handle->m_vtable = vtable; handle->m_platform = platform; @@ -69,10 +55,7 @@ int32_t scap_init_live_int(scap_t* handle, scap_open_args* oargs, const struct s handle->m_debug_log_fn = oargs->debug_log_fn; - // - // Open and initialize all the devices - // - if((rc = handle->m_vtable->init(handle, oargs)) != SCAP_SUCCESS) + if(handle->m_vtable->init && (rc = handle->m_vtable->init(handle, oargs)) != SCAP_SUCCESS) { return rc; } @@ -92,230 +75,6 @@ int32_t scap_init_live_int(scap_t* handle, scap_open_args* oargs, const struct s return SCAP_SUCCESS; } -#endif // HAS_LIVE_CAPTURE - -#ifdef HAS_ENGINE_UDIG -int32_t scap_init_udig_int(scap_t* handle, scap_open_args* oargs, struct scap_platform* platform) -{ - int32_t rc; - - // - // Preliminary initializations - // - handle->m_mode = SCAP_MODE_LIVE; - handle->m_vtable = &scap_udig_engine; - handle->m_platform = platform; - - handle->m_engine.m_handle = handle->m_vtable->alloc_handle(handle, handle->m_lasterr); - if(!handle->m_engine.m_handle) - { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error allocating the engine structure"); - return SCAP_FAILURE; - } - - rc = handle->m_vtable->init(handle, oargs); - if(rc != SCAP_SUCCESS) - { - return rc; - } - - handle->m_debug_log_fn = oargs->debug_log_fn; - - // - // Additional initializations - // - scap_stop_dropping_mode(handle); - - // - // Now that /proc parsing has been done, start the capture - // - if((rc = udig_begin_capture(handle->m_engine, handle->m_lasterr)) != SCAP_SUCCESS) - { - return rc; - } - - if((rc = scap_platform_init(handle->m_platform, handle->m_lasterr, handle->m_engine, oargs)) != SCAP_SUCCESS) - { - return rc; - } - - return SCAP_SUCCESS; -} -#endif // HAS_ENGINE_UDIG - -#ifdef HAS_ENGINE_TEST_INPUT -int32_t scap_init_test_input_int(scap_t* handle, scap_open_args* oargs, struct scap_platform *platform) -{ - int32_t rc; - - // - // Preliminary initializations - // - handle->m_mode = oargs->mode; - handle->m_vtable = &scap_test_input_engine; - handle->m_platform = platform; - - handle->m_engine.m_handle = handle->m_vtable->alloc_handle(handle, handle->m_lasterr); - if(!handle->m_engine.m_handle) - { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error allocating the engine structure"); - return SCAP_FAILURE; - } - - rc = handle->m_vtable->init(handle, oargs); - if(rc != SCAP_SUCCESS) - { - return rc; - } - - handle->m_debug_log_fn = oargs->debug_log_fn; - - if((rc = scap_platform_init(handle->m_platform, handle->m_lasterr, handle->m_engine, oargs)) != SCAP_SUCCESS) - { - return rc; - } - - return SCAP_SUCCESS; -} -#endif - -#ifdef HAS_ENGINE_GVISOR -int32_t scap_init_gvisor_int(scap_t* handle, scap_open_args* oargs, struct scap_platform *platform) -{ - int32_t rc; - - // - // Preliminary initializations - // - handle->m_mode = SCAP_MODE_LIVE; - handle->m_vtable = &scap_gvisor_engine; - handle->m_platform = platform; - - handle->m_engine.m_handle = handle->m_vtable->alloc_handle(handle, handle->m_lasterr); - if(!handle->m_engine.m_handle) - { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error allocating the engine structure"); - return SCAP_FAILURE; - } - - rc = handle->m_vtable->init(handle, oargs); - if(rc != SCAP_SUCCESS) - { - return rc; - } - - handle->m_debug_log_fn = oargs->debug_log_fn; - - if((rc = scap_platform_init(handle->m_platform, handle->m_lasterr, handle->m_engine, oargs)) != SCAP_SUCCESS) - { - return rc; - } - - return SCAP_SUCCESS; -} -#endif // HAS_ENGINE_GVISOR - -#ifdef HAS_ENGINE_SAVEFILE -int32_t scap_init_offline_int(scap_t* handle, scap_open_args* oargs, struct scap_platform* platform) -{ - int32_t rc; - - // - // Preliminary initializations - // - handle->m_mode = SCAP_MODE_CAPTURE; - handle->m_vtable = &scap_savefile_engine; - handle->m_platform = platform; - - handle->m_engine.m_handle = handle->m_vtable->alloc_handle(handle, handle->m_lasterr); - if(!handle->m_engine.m_handle) - { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error allocating the engine structure"); - return SCAP_FAILURE; - } - - handle->m_evtcnt = 0; - - handle->m_debug_log_fn = oargs->debug_log_fn; - - if((rc = handle->m_vtable->init(handle, oargs)) != SCAP_SUCCESS) - { - return rc; - } - - if((rc = scap_platform_init(handle->m_platform, handle->m_lasterr, handle->m_engine, oargs)) != SCAP_SUCCESS) - { - return rc; - } - - return SCAP_SUCCESS; -} -#endif - -#ifdef HAS_ENGINE_NODRIVER -int32_t scap_init_nodriver_int(scap_t* handle, scap_open_args* oargs, struct scap_platform *platform) -{ - int32_t rc; - - // - // Preliminary initializations - // - handle->m_mode = SCAP_MODE_NODRIVER; - handle->m_vtable = &scap_nodriver_engine; - handle->m_platform = platform; - - handle->m_engine.m_handle = handle->m_vtable->alloc_handle(handle, handle->m_lasterr); - if(!handle->m_engine.m_handle) - { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error allocating the engine structure"); - return SCAP_FAILURE; - } - - handle->m_debug_log_fn = oargs->debug_log_fn; - - if((rc = scap_platform_init(handle->m_platform, handle->m_lasterr, handle->m_engine, oargs)) != SCAP_SUCCESS) - { - return rc; - } - - return SCAP_SUCCESS; -} -#endif // HAS_ENGINE_NODRIVER - -#ifdef HAS_ENGINE_SOURCE_PLUGIN -int32_t scap_init_plugin_int(scap_t* handle, scap_open_args* oargs, struct scap_platform* platform) -{ - int32_t rc; - - // - // Preliminary initializations - // - handle->m_mode = SCAP_MODE_PLUGIN; - handle->m_vtable = &scap_source_plugin_engine; - handle->m_platform = platform; - - handle->m_engine.m_handle = handle->m_vtable->alloc_handle(handle, handle->m_lasterr); - if(!handle->m_engine.m_handle) - { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error allocating the engine structure"); - return SCAP_FAILURE; - } - - handle->m_debug_log_fn = oargs->debug_log_fn; - - if((rc = handle->m_vtable->init(handle, oargs)) != SCAP_SUCCESS) - { - return rc; - } - - if((rc = scap_platform_init(handle->m_platform, handle->m_lasterr, handle->m_engine, oargs)) != SCAP_SUCCESS) - { - return rc; - } - - return SCAP_SUCCESS; -} -#endif scap_t* scap_alloc(void) { @@ -326,6 +85,7 @@ int32_t scap_init(scap_t* handle, scap_open_args* oargs) { const char* engine_name = oargs->engine_name; struct scap_platform* platform = NULL; + const struct scap_vtable* vtable = NULL; memset(handle, 0, sizeof(*handle)); @@ -336,42 +96,28 @@ int32_t scap_init(scap_t* handle, scap_open_args* oargs) #ifdef HAS_ENGINE_SAVEFILE if(strcmp(engine_name, SAVEFILE_ENGINE) == 0) { + vtable = &scap_savefile_engine; platform = scap_savefile_alloc_platform(); - if(!platform) - { - return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform struct"); - } - - return scap_init_offline_int(handle, oargs, platform); } #endif #ifdef HAS_ENGINE_UDIG if(strcmp(engine_name, UDIG_ENGINE) == 0) { + vtable = &scap_udig_engine; platform = scap_linux_alloc_platform(); - if(!platform) - { - return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform struct"); - } - - return scap_init_udig_int(handle, oargs, platform); } #endif #ifdef HAS_ENGINE_GVISOR if(strcmp(engine_name, GVISOR_ENGINE) == 0) { + vtable = &scap_gvisor_engine; platform = scap_gvisor_alloc_platform(); - if(!platform) - { - return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform struct"); - } - - return scap_init_gvisor_int(handle, oargs, platform); } #endif #ifdef HAS_ENGINE_TEST_INPUT if(strcmp(engine_name, TEST_INPUT_ENGINE) == 0) { + vtable = &scap_test_input_engine; if(oargs->mode == SCAP_MODE_LIVE) { platform = scap_linux_alloc_platform(); @@ -380,86 +126,66 @@ int32_t scap_init(scap_t* handle, scap_open_args* oargs) { platform = scap_test_input_alloc_platform(); } - if(!platform) - { - return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform struct"); - } - - return scap_init_test_input_int(handle, oargs, platform); } #endif #ifdef HAS_ENGINE_KMOD if(strcmp(engine_name, KMOD_ENGINE) == 0) { + vtable = &scap_kmod_engine; platform = scap_linux_alloc_platform(); - if(!platform) + if(platform) { - return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform struct"); + ((struct scap_linux_platform*)platform)->m_linux_vtable = &scap_kmod_linux_vtable; } - - ((struct scap_linux_platform*)platform)->m_linux_vtable = &scap_kmod_linux_vtable; - - return scap_init_live_int(handle, oargs, &scap_kmod_engine, platform); } #endif #ifdef HAS_ENGINE_BPF if(strcmp(engine_name, BPF_ENGINE) == 0) { + vtable = &scap_bpf_engine; platform = scap_linux_alloc_platform(); - if(!platform) - { - return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform struct"); - } - - return scap_init_live_int(handle, oargs, &scap_bpf_engine, platform); } #endif #ifdef HAS_ENGINE_MODERN_BPF if(strcmp(engine_name, MODERN_BPF_ENGINE) == 0) { + vtable = &scap_modern_bpf_engine; platform = scap_linux_alloc_platform(); - if(!platform) - { - return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform struct"); - } - - return scap_init_live_int(handle, oargs, &scap_modern_bpf_engine, platform); } #endif #ifdef HAS_ENGINE_NODRIVER if(strcmp(engine_name, NODRIVER_ENGINE) == 0) { + vtable = &scap_nodriver_engine; platform = scap_linux_alloc_platform(); - if(!platform) - { - return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform struct"); - } - struct scap_nodriver_engine_params* engine_params = oargs->engine_params; - if(!engine_params || !engine_params->full_proc_scan) + + if(platform && (!engine_params || !engine_params->full_proc_scan)) { ((struct scap_linux_platform*)platform)->m_fd_lookup_limit = SCAP_NODRIVER_MAX_FD_LOOKUP; ((struct scap_linux_platform*)platform)->m_minimal_scan = true; } - - return scap_init_nodriver_int(handle, oargs, platform); } #endif #ifdef HAS_ENGINE_SOURCE_PLUGIN if(strcmp(engine_name, SOURCE_PLUGIN_ENGINE) == 0) { + vtable = &scap_source_plugin_engine; platform = scap_generic_alloc_platform(); - if(!platform) - { - return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform struct"); - } - - return scap_init_plugin_int(handle, oargs, platform); } #endif - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "incorrect engine '%s'", engine_name); - return SCAP_FAILURE; + if(!vtable) + { + return scap_errprintf(handle->m_lasterr, 0, "incorrect engine '%s'", engine_name); + } + + if(!platform) + { + return scap_errprintf(handle->m_lasterr, 0, "failed to allocate platform data"); + } + + return scap_init_int(handle, oargs, vtable, platform); } scap_t* scap_open(scap_open_args* oargs, char *error, int32_t *rc) diff --git a/userspace/libscap/scap_api_version.c b/userspace/libscap/scap_api_version.c new file mode 100644 index 00000000000..153b05b565a --- /dev/null +++ b/userspace/libscap/scap_api_version.c @@ -0,0 +1,98 @@ +/* +Copyright (C) 2023 The Falco Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#include "scap_api_version.h" +#include "scap.h" +#include "scap_engine_util.h" +#include "scap_vtable.h" +#include "strerror.h" + + +bool scap_apply_semver_check(uint32_t current_major, uint32_t current_minor, uint32_t current_patch, + uint32_t required_major, uint32_t required_minor, uint32_t required_patch) +{ + if(current_major != required_major) + { + return false; + } + + if(current_minor < required_minor) + { + return false; + } + if(current_minor == required_minor && current_patch < required_patch) + { + return false; + } + + return true; +} + +bool scap_is_api_compatible(unsigned long driver_api_version, unsigned long required_api_version) +{ + unsigned long driver_major = PPM_API_VERSION_MAJOR(driver_api_version); + unsigned long driver_minor = PPM_API_VERSION_MINOR(driver_api_version); + unsigned long driver_patch = PPM_API_VERSION_PATCH(driver_api_version); + unsigned long required_major = PPM_API_VERSION_MAJOR(required_api_version); + unsigned long required_minor = PPM_API_VERSION_MINOR(required_api_version); + unsigned long required_patch = PPM_API_VERSION_PATCH(required_api_version); + + return scap_apply_semver_check(driver_major, driver_minor, driver_patch, required_major, required_minor, required_patch); +} + +static int32_t check_api_compatibility_impl(uint64_t current_version, uint64_t minimum_version, const char* label, char *error) +{ + if(!scap_is_api_compatible(current_version, minimum_version)) + { + return scap_errprintf(error, 0, "Driver supports %s version %llu.%llu.%llu, but running version needs %llu.%llu.%llu", + label, + PPM_API_VERSION_MAJOR(current_version), + PPM_API_VERSION_MINOR(current_version), + PPM_API_VERSION_PATCH(current_version), + PPM_API_VERSION_MAJOR(minimum_version), + PPM_API_VERSION_MINOR(minimum_version), + PPM_API_VERSION_PATCH(minimum_version)); + } + return SCAP_SUCCESS; +} + +int32_t check_api_compatibility(const struct scap_vtable* vtable, struct scap_engine_handle engine, char *error) +{ + int rc; + if(vtable && vtable->get_api_version) + { + uint64_t version = vtable->get_api_version(engine); + rc = check_api_compatibility_impl(version, SCAP_MINIMUM_DRIVER_API_VERSION, "API", error); + if(rc != SCAP_SUCCESS) + { + return rc; + } + } + + if(vtable && vtable->get_schema_version) + { + uint64_t version = vtable->get_schema_version(engine); + rc = check_api_compatibility_impl(version, SCAP_MINIMUM_DRIVER_SCHEMA_VERSION, "schema", error); + if(rc != SCAP_SUCCESS) + { + return rc; + } + } + + return SCAP_SUCCESS; +} + diff --git a/userspace/libscap/scap_api_version.h b/userspace/libscap/scap_api_version.h new file mode 100644 index 00000000000..1a56830930b --- /dev/null +++ b/userspace/libscap/scap_api_version.h @@ -0,0 +1,43 @@ +/* +Copyright (C) 2023 The Falco Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#pragma once + +#include +#include + +#ifndef SCAP_HANDLE_T +#define SCAP_HANDLE_T void +#endif + +#include "engine_handle.h" + +struct scap_vtable; + +/** + * Is `driver_api_version` compatible with `required_api_version`? + */ +bool scap_is_api_compatible(unsigned long driver_api_version, unsigned long required_api_version); + +/** + * Apply the `semver` checks on current and required versions. + */ +bool scap_apply_semver_check(uint32_t current_major, uint32_t current_minor, uint32_t current_patch, + uint32_t required_major, uint32_t required_minor, uint32_t required_patch); + +int32_t check_api_compatibility(const struct scap_vtable* vtable, struct scap_engine_handle engine, char *error); + diff --git a/userspace/libscap/scap_engine_util.c b/userspace/libscap/scap_engine_util.c index 713cdd2249f..e7b8a02bf58 100644 --- a/userspace/libscap/scap_engine_util.c +++ b/userspace/libscap/scap_engine_util.c @@ -19,89 +19,11 @@ limitations under the License. #include #include -#include "scap.h" -#include "scap-int.h" #include "scap_engine_util.h" -#include "scap_vtable.h" +#include "scap_const.h" #include "strerror.h" -#ifdef __linux__ #include "compat/misc.h" -#endif - -bool scap_apply_semver_check(uint32_t current_major, uint32_t current_minor, uint32_t current_patch, - uint32_t required_major, uint32_t required_minor, uint32_t required_patch) -{ - if(current_major != required_major) - { - return false; - } - - if(current_minor < required_minor) - { - return false; - } - if(current_minor == required_minor && current_patch < required_patch) - { - return false; - } - - return true; -} - -bool scap_is_api_compatible(unsigned long driver_api_version, unsigned long required_api_version) -{ - unsigned long driver_major = PPM_API_VERSION_MAJOR(driver_api_version); - unsigned long driver_minor = PPM_API_VERSION_MINOR(driver_api_version); - unsigned long driver_patch = PPM_API_VERSION_PATCH(driver_api_version); - unsigned long required_major = PPM_API_VERSION_MAJOR(required_api_version); - unsigned long required_minor = PPM_API_VERSION_MINOR(required_api_version); - unsigned long required_patch = PPM_API_VERSION_PATCH(required_api_version); - - return scap_apply_semver_check(driver_major, driver_minor, driver_patch, required_major, required_minor, required_patch); -} - -static int32_t check_api_compatibility_impl(uint64_t current_version, uint64_t minimum_version, const char* label, char *error) -{ - if(!scap_is_api_compatible(current_version, minimum_version)) - { - return scap_errprintf(error, 0, "Driver supports %s version %llu.%llu.%llu, but running version needs %llu.%llu.%llu", - label, - PPM_API_VERSION_MAJOR(current_version), - PPM_API_VERSION_MINOR(current_version), - PPM_API_VERSION_PATCH(current_version), - PPM_API_VERSION_MAJOR(minimum_version), - PPM_API_VERSION_MINOR(minimum_version), - PPM_API_VERSION_PATCH(minimum_version)); - } - return SCAP_SUCCESS; -} - - int32_t check_api_compatibility(const struct scap_vtable* vtable, struct scap_engine_handle engine, char *error) -{ - int rc; - if(vtable && vtable->get_api_version) - { - uint64_t version = vtable->get_api_version(engine); - rc = check_api_compatibility_impl(version, SCAP_MINIMUM_DRIVER_API_VERSION, "API", error); - if(rc != SCAP_SUCCESS) - { - return rc; - } - } - - if(vtable && vtable->get_schema_version) - { - uint64_t version = vtable->get_schema_version(engine); - rc = check_api_compatibility_impl(version, SCAP_MINIMUM_DRIVER_SCHEMA_VERSION, "schema", error); - if(rc != SCAP_SUCCESS) - { - return rc; - } - } - - return SCAP_SUCCESS; -} static inline uint64_t timespec_to_nsec(const struct timespec* ts) { @@ -110,7 +32,6 @@ static inline uint64_t timespec_to_nsec(const struct timespec* ts) int32_t scap_get_precise_boot_time(char* last_err, uint64_t *boot_time) { -#ifdef __linux__ struct timespec wall_ts, boot_ts; if(clock_gettime(CLOCK_BOOTTIME, &boot_ts) < 0) @@ -125,7 +46,4 @@ int32_t scap_get_precise_boot_time(char* last_err, uint64_t *boot_time) *boot_time = timespec_to_nsec(&wall_ts) - timespec_to_nsec(&boot_ts); return SCAP_SUCCESS; -#else - return scap_errprintf(last_err, 0, "scap_get_precise_boot_time not implemented on this platform"); -#endif } diff --git a/userspace/libscap/scap_engine_util.h b/userspace/libscap/scap_engine_util.h index 27c07835d17..7e1612cbd3a 100644 --- a/userspace/libscap/scap_engine_util.h +++ b/userspace/libscap/scap_engine_util.h @@ -20,27 +20,6 @@ limitations under the License. #include #include -#ifndef SCAP_HANDLE_T -#define SCAP_HANDLE_T void -#endif - -#include "engine_handle.h" - -struct scap_vtable; - -/** - * Is `driver_api_version` compatible with `required_api_version`? - */ -bool scap_is_api_compatible(unsigned long driver_api_version, unsigned long required_api_version); - -/** - * Apply the `semver` checks on current and required versions. - */ -bool scap_apply_semver_check(uint32_t current_major, uint32_t current_minor, uint32_t current_patch, - uint32_t required_major, uint32_t required_minor, uint32_t required_patch); - -int32_t check_api_compatibility(const struct scap_vtable* vtable, struct scap_engine_handle engine, char *error); - /** * \brief Get the timestamp of boot with subsecond accuracy * diff --git a/userspace/libscap/scap_savefile.c b/userspace/libscap/scap_savefile.c index 5cd985e5dbe..f10b46bcea8 100755 --- a/userspace/libscap/scap_savefile.c +++ b/userspace/libscap/scap_savefile.c @@ -34,6 +34,7 @@ struct iovec { #include "scap_platform_impl.h" #include "scap_savefile_api.h" #include "scap_savefile.h" +#include "strl.h" const char* scap_dump_getlasterr(scap_dumper_t* d) { @@ -1033,7 +1034,7 @@ static int32_t scap_write_userlist(scap_dumper_t* d, struct scap_userlist *userl // // Create the dump file headers and add the tables // -static int32_t scap_setup_dump(scap_t *handle, scap_dumper_t* d, const char *fname) +static int32_t scap_setup_dump(scap_dumper_t* d, struct scap_platform *platform, const char *fname) { block_header bh; section_header_block sh; @@ -1060,12 +1061,12 @@ static int32_t scap_setup_dump(scap_t *handle, scap_dumper_t* d, const char *fna return SCAP_FAILURE; } - if(handle->m_mode != SCAP_MODE_PLUGIN) + if(platform) { // // Write the machine info // - if(scap_write_machine_info(d, &handle->m_platform->m_machine_info) != SCAP_SUCCESS) + if(scap_write_machine_info(d, &platform->m_machine_info) != SCAP_SUCCESS) { return SCAP_FAILURE; } @@ -1073,7 +1074,7 @@ static int32_t scap_setup_dump(scap_t *handle, scap_dumper_t* d, const char *fna // // Write the interface list // - if(scap_write_iflist(d, handle->m_platform->m_addrlist) != SCAP_SUCCESS) + if(scap_write_iflist(d, platform->m_addrlist) != SCAP_SUCCESS) { return SCAP_FAILURE; } @@ -1081,7 +1082,7 @@ static int32_t scap_setup_dump(scap_t *handle, scap_dumper_t* d, const char *fna // // Write the user list // - if(scap_write_userlist(d, handle->m_platform->m_userlist) != SCAP_SUCCESS) + if(scap_write_userlist(d, platform->m_userlist) != SCAP_SUCCESS) { return SCAP_FAILURE; } @@ -1089,7 +1090,7 @@ static int32_t scap_setup_dump(scap_t *handle, scap_dumper_t* d, const char *fna // // Write the process list // - if(scap_write_proclist(d, &handle->m_platform->m_proclist) != SCAP_SUCCESS) + if(scap_write_proclist(d, &platform->m_proclist) != SCAP_SUCCESS) { return SCAP_FAILURE; } @@ -1097,7 +1098,7 @@ static int32_t scap_setup_dump(scap_t *handle, scap_dumper_t* d, const char *fna // // Write the fd lists // - if(scap_write_fdlist(d, &handle->m_platform->m_proclist) != SCAP_SUCCESS) + if(scap_write_fdlist(d, &platform->m_proclist) != SCAP_SUCCESS) { return SCAP_FAILURE; } @@ -1109,20 +1110,23 @@ static int32_t scap_setup_dump(scap_t *handle, scap_dumper_t* d, const char *fna return SCAP_SUCCESS; } -static inline int32_t scap_dump_rescan_proc(scap_t *handle) +static inline int32_t scap_dump_rescan_proc(struct scap_platform* platform) { int32_t ret = SCAP_SUCCESS; #ifdef __linux__ - proc_entry_callback tcb = handle->m_platform->m_proclist.m_proc_callback; - handle->m_platform->m_proclist.m_proc_callback = NULL; - ret = scap_refresh_proc_table(handle); - handle->m_platform->m_proclist.m_proc_callback = tcb; + if(platform && platform->m_vtable && platform->m_vtable->refresh_proc_table) + { + proc_entry_callback tcb = platform->m_proclist.m_proc_callback; + platform->m_proclist.m_proc_callback = NULL; + ret = platform->m_vtable->refresh_proc_table(platform, &platform->m_proclist); + platform->m_proclist.m_proc_callback = tcb; + } #endif return ret; } // fname is only used for log messages in scap_setup_dump -static scap_dumper_t *scap_dump_open_gzfile(scap_t *handle, gzFile gzfile, const char *fname, bool skip_proc_scan) +static scap_dumper_t *scap_dump_open_gzfile(struct scap_platform* platform, gzFile gzfile, const char *fname, char* lasterr) { scap_dumper_t* res = (scap_dumper_t*)malloc(sizeof(scap_dumper_t)); res->m_f = gzfile; @@ -1131,9 +1135,9 @@ static scap_dumper_t *scap_dump_open_gzfile(scap_t *handle, gzFile gzfile, const res->m_targetbufcurpos = NULL; res->m_targetbufend = NULL; - if(scap_setup_dump(handle, res, fname) != SCAP_SUCCESS) + if(scap_setup_dump(res, platform, fname) != SCAP_SUCCESS) { - strcpy(handle->m_lasterr, res->m_lasterr); + strlcpy(lasterr, res->m_lasterr, SCAP_LASTERR_SIZE); free(res); res = NULL; } @@ -1144,7 +1148,7 @@ static scap_dumper_t *scap_dump_open_gzfile(scap_t *handle, gzFile gzfile, const // // Open a "savefile" for writing. // -scap_dumper_t *scap_dump_open(scap_t *handle, const char *fname, compression_mode compress, bool skip_proc_scan) +scap_dumper_t *scap_dump_open(struct scap_platform* platform, const char *fname, compression_mode compress, bool skip_proc_scan, char* lasterr) { gzFile f = NULL; int fd = -1; @@ -1161,7 +1165,7 @@ scap_dumper_t *scap_dump_open(scap_t *handle, const char *fname, compression_mod break; default: ASSERT(false); - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "invalid compression mode"); + snprintf(lasterr, SCAP_LASTERR_SIZE, "invalid compression mode"); return NULL; } @@ -1192,7 +1196,7 @@ scap_dumper_t *scap_dump_open(scap_t *handle, const char *fname, compression_mod } #endif - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "can't open %s", fname); + snprintf(lasterr, SCAP_LASTERR_SIZE, "can't open %s", fname); return NULL; } @@ -1201,21 +1205,21 @@ scap_dumper_t *scap_dump_open(scap_t *handle, const char *fname, compression_mod // so we don't lose information about processes created in the interval // between opening the handle and starting the dump // - if(handle->m_mode != SCAP_MODE_CAPTURE && !skip_proc_scan) + if(!skip_proc_scan) { - if(scap_dump_rescan_proc(handle) != SCAP_SUCCESS) + if(scap_dump_rescan_proc(platform) != SCAP_SUCCESS) { return NULL; } } - res = scap_dump_open_gzfile(handle, f, fname, skip_proc_scan); + res = scap_dump_open_gzfile(platform, f, fname, lasterr); // // If the user doesn't need the thread table, free it // - if(handle->m_platform->m_proclist.m_proc_callback != NULL) + if(platform->m_proclist.m_proc_callback != NULL) { - scap_proc_free_table(&handle->m_platform->m_proclist); + scap_proc_free_table(&platform->m_proclist); } return res; @@ -1223,7 +1227,7 @@ scap_dumper_t *scap_dump_open(scap_t *handle, const char *fname, compression_mod // // Open a savefile for writing, using the provided fd -scap_dumper_t* scap_dump_open_fd(scap_t *handle, int fd, compression_mode compress, bool skip_proc_scan) +scap_dumper_t* scap_dump_open_fd(struct scap_platform* platform, int fd, compression_mode compress, bool skip_proc_scan, char* lasterr) { gzFile f = NULL; scap_dumper_t* res; @@ -1238,13 +1242,13 @@ scap_dumper_t* scap_dump_open_fd(scap_t *handle, int fd, compression_mode compre break; default: ASSERT(false); - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "invalid compression mode"); + snprintf(lasterr, SCAP_LASTERR_SIZE, "invalid compression mode"); return NULL; } if(f == NULL) { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "can't open fd %d", fd); + snprintf(lasterr, SCAP_LASTERR_SIZE, "can't open fd %d", fd); return NULL; } @@ -1253,22 +1257,22 @@ scap_dumper_t* scap_dump_open_fd(scap_t *handle, int fd, compression_mode compre // so we don't lose information about processes created in the interval // between opening the handle and starting the dump // - if(handle->m_mode != SCAP_MODE_CAPTURE && !skip_proc_scan) + if(!skip_proc_scan) { - if(scap_dump_rescan_proc(handle) != SCAP_SUCCESS) + if(scap_dump_rescan_proc(platform) != SCAP_SUCCESS) { return NULL; } } - res = scap_dump_open_gzfile(handle, f, "", skip_proc_scan); + res = scap_dump_open_gzfile(platform, f, "", lasterr); // // If the user doesn't need the thread table, free it // - if(handle->m_platform->m_proclist.m_proc_callback != NULL) + if(platform->m_proclist.m_proc_callback != NULL) { - scap_proc_free_table(&handle->m_platform->m_proclist); + scap_proc_free_table(&platform->m_proclist); } return res; } @@ -1276,12 +1280,12 @@ scap_dumper_t* scap_dump_open_fd(scap_t *handle, int fd, compression_mode compre // // Open a memory "savefile" // -scap_dumper_t *scap_memory_dump_open(scap_t *handle, uint8_t* targetbuf, uint64_t targetbufsize) +scap_dumper_t *scap_memory_dump_open(struct scap_platform* platform, uint8_t* targetbuf, uint64_t targetbufsize, char* lasterr) { scap_dumper_t* res = (scap_dumper_t*)malloc(sizeof(scap_dumper_t)); if(res == NULL) { - snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "scap_dump_memory_open memory allocation failure (1)"); + snprintf(lasterr, SCAP_LASTERR_SIZE, "scap_dump_memory_open memory allocation failure (1)"); return NULL; } @@ -1291,9 +1295,9 @@ scap_dumper_t *scap_memory_dump_open(scap_t *handle, uint8_t* targetbuf, uint64_ res->m_targetbufcurpos = targetbuf; res->m_targetbufend = targetbuf + targetbufsize; - if(scap_setup_dump(handle, res, "") != SCAP_SUCCESS) + if(scap_setup_dump(res, platform, "") != SCAP_SUCCESS) { - strcpy(handle->m_lasterr, res->m_lasterr); + strlcpy(lasterr, res->m_lasterr, SCAP_LASTERR_SIZE); free(res); res = NULL; } diff --git a/userspace/libscap/scap_savefile_api.h b/userspace/libscap/scap_savefile_api.h index 1b64846f887..43db61beb0d 100644 --- a/userspace/libscap/scap_savefile_api.h +++ b/userspace/libscap/scap_savefile_api.h @@ -27,6 +27,8 @@ limitations under the License. extern "C" { #endif +struct scap_platform; + typedef enum ppm_dumper_type { DT_FILE = 0, @@ -47,7 +49,6 @@ typedef struct scap_dumper char m_lasterr[SCAP_LASTERR_SIZE]; } scap_dumper_t; -typedef struct scap scap_t; struct scap_threadinfo; typedef struct ppm_evt_hdr scap_evt; struct iovec; @@ -65,7 +66,7 @@ uint8_t* scap_get_memorydumper_curpos(scap_dumper_t *d); int32_t scap_write_proc_fds(scap_dumper_t *d, struct scap_threadinfo *tinfo); scap_dumper_t* scap_write_proclist_begin(); int scap_write_proclist_end(scap_dumper_t *d, scap_dumper_t *proclist_dumper, uint32_t totlen); -scap_dumper_t *scap_memory_dump_open(scap_t *handle, uint8_t* targetbuf, uint64_t targetbufsize); +scap_dumper_t *scap_memory_dump_open(struct scap_platform* platform, uint8_t* targetbuf, uint64_t targetbufsize, char* lasterr); scap_dumper_t *scap_managedbuf_dump_create(); // Variant of scap_write_proclist_entry where array-backed information @@ -89,7 +90,7 @@ int32_t scap_write_proclist_entry_bufs(scap_dumper_t *d, struct scap_threadinfo \return Dump handle that can be used to identify this specific dump instance. */ -scap_dumper_t* scap_dump_open(scap_t *handle, const char *fname, compression_mode compress, bool skip_proc_scan); +scap_dumper_t *scap_dump_open(struct scap_platform* platform, const char *fname, compression_mode compress, bool skip_proc_scan, char* lasterr); /*! \brief Open a trace file for writing, using the provided fd. @@ -99,7 +100,7 @@ scap_dumper_t* scap_dump_open(scap_t *handle, const char *fname, compression_mod \return Dump handle that can be used to identify this specific dump instance. */ -scap_dumper_t* scap_dump_open_fd(scap_t *handle, int fd, compression_mode compress, bool skip_proc_scan); +scap_dumper_t* scap_dump_open_fd(struct scap_platform* platform, int fd, compression_mode compress, bool skip_proc_scan, char* lasterr); /*! \brief Close a trace file. diff --git a/userspace/libsinsp/dumper.cpp b/userspace/libsinsp/dumper.cpp index 7d410bed51a..95bd4acc071 100644 --- a/userspace/libsinsp/dumper.cpp +++ b/userspace/libsinsp/dumper.cpp @@ -18,6 +18,7 @@ limitations under the License. #include "sinsp.h" #include "sinsp_int.h" #include "scap.h" +#include "scap-int.h" // for scap_t->m_platform #include "dumper.h" sinsp_dumper::sinsp_dumper() @@ -45,6 +46,7 @@ sinsp_dumper::~sinsp_dumper() void sinsp_dumper::open(sinsp* inspector, const std::string& filename, bool compress, bool threads_from_sinsp) { + char error[SCAP_LASTERR_SIZE]; if(inspector->m_h == NULL) { throw sinsp_exception("can't start event dump, inspector not opened yet"); @@ -52,23 +54,23 @@ void sinsp_dumper::open(sinsp* inspector, const std::string& filename, bool comp if(m_target_memory_buffer) { - m_dumper = scap_memory_dump_open(inspector->m_h, m_target_memory_buffer, m_target_memory_buffer_size); + m_dumper = scap_memory_dump_open(inspector->m_h->m_platform, m_target_memory_buffer, m_target_memory_buffer_size, error); } else { if(compress) { - m_dumper = scap_dump_open(inspector->m_h, filename.c_str(), SCAP_COMPRESSION_GZIP, threads_from_sinsp); + m_dumper = scap_dump_open(inspector->m_h->m_platform, filename.c_str(), SCAP_COMPRESSION_GZIP, threads_from_sinsp, error); } else { - m_dumper = scap_dump_open(inspector->m_h, filename.c_str(), SCAP_COMPRESSION_NONE, threads_from_sinsp); + m_dumper = scap_dump_open(inspector->m_h->m_platform, filename.c_str(), SCAP_COMPRESSION_NONE, threads_from_sinsp, error); } } - if(m_dumper == NULL) + if(m_dumper == nullptr) { - throw sinsp_exception(scap_getlasterr(inspector->m_h)); + throw sinsp_exception(error); } if(threads_from_sinsp) @@ -85,6 +87,7 @@ void sinsp_dumper::open(sinsp* inspector, const std::string& filename, bool comp void sinsp_dumper::fdopen(sinsp* inspector, int fd, bool compress, bool threads_from_sinsp) { + char error[SCAP_LASTERR_SIZE]; if(inspector->m_h == NULL) { throw sinsp_exception("can't start event dump, inspector not opened yet"); @@ -92,16 +95,16 @@ void sinsp_dumper::fdopen(sinsp* inspector, int fd, bool compress, bool threads_ if(compress) { - m_dumper = scap_dump_open_fd(inspector->m_h, fd, SCAP_COMPRESSION_GZIP, threads_from_sinsp); + m_dumper = scap_dump_open_fd(inspector->m_h->m_platform, fd, SCAP_COMPRESSION_GZIP, threads_from_sinsp, error); } else { - m_dumper = scap_dump_open_fd(inspector->m_h, fd, SCAP_COMPRESSION_NONE, threads_from_sinsp); + m_dumper = scap_dump_open_fd(inspector->m_h->m_platform, fd, SCAP_COMPRESSION_NONE, threads_from_sinsp, error); } - if(m_dumper == NULL) + if(m_dumper == nullptr) { - throw sinsp_exception(scap_getlasterr(inspector->m_h)); + throw sinsp_exception(error); } if(threads_from_sinsp)