diff --git a/userspace/libscap/linux/CMakeLists.txt b/userspace/libscap/linux/CMakeLists.txt index 471721f4e2..4d51534ca0 100644 --- a/userspace/libscap/linux/CMakeLists.txt +++ b/userspace/libscap/linux/CMakeLists.txt @@ -14,7 +14,16 @@ # See the License for the specific language governing permissions and # limitations under the License. # -add_library(scap_platform STATIC scap_linux_platform.c scap_procs.c scap_fds.c scap_userlist.c scap_iflist.c scap_cgroup.c scap_machine_info.c) +add_library(scap_platform + STATIC + scap_linux_platform.c + scap_linux_hostinfo_platform.c + scap_procs.c + scap_fds.c + scap_userlist.c + scap_iflist.c + scap_cgroup.c + scap_machine_info.c) target_include_directories(scap_platform PUBLIC $) target_link_libraries(scap_platform PRIVATE scap_error scap_platform_util) add_dependencies(scap_platform uthash) diff --git a/userspace/libscap/linux/scap_linux_hostinfo_platform.c b/userspace/libscap/linux/scap_linux_hostinfo_platform.c new file mode 100644 index 0000000000..258d591919 --- /dev/null +++ b/userspace/libscap/linux/scap_linux_hostinfo_platform.c @@ -0,0 +1,73 @@ +/* +Copyright (C) 2024 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 + +#include +#include +#include +#include + +#include +#include + +static void scap_linux_hostinfo_free_platform(struct scap_platform* platform) +{ + free(platform); +} + +int32_t scap_linux_hostinfo_init_platform(struct scap_platform* platform, char* lasterr, struct scap_engine_handle engine, struct scap_open_args* oargs) +{ + int rc; + + if(scap_os_get_machine_info(&platform->m_machine_info, lasterr) != SCAP_SUCCESS) + { + return SCAP_FAILURE; + } + + scap_os_get_agent_info(&platform->m_agent_info); + + rc = scap_linux_create_iflist(platform); + if(rc != SCAP_SUCCESS) + { + scap_linux_hostinfo_free_platform(platform); + return rc; + } + + return SCAP_SUCCESS; +} + +static const struct scap_platform_vtable scap_linux_hostinfo_platform_vtable = { + .init_platform = scap_linux_hostinfo_init_platform, + .refresh_addr_list = scap_linux_create_iflist, + .free_platform = scap_linux_hostinfo_free_platform, +}; + +struct scap_platform* scap_linux_hostinfo_alloc_platform() +{ + struct scap_linux_platform* platform = calloc(1, sizeof(*platform)); + + if(platform == NULL) + { + return NULL; + } + + struct scap_platform* generic = &platform->m_generic; + generic->m_vtable = &scap_linux_hostinfo_platform_vtable; + + return generic; +} diff --git a/userspace/libscap/linux/scap_linux_platform.h b/userspace/libscap/linux/scap_linux_platform.h index 55de6a66d0..c08327873e 100644 --- a/userspace/libscap/linux/scap_linux_platform.h +++ b/userspace/libscap/linux/scap_linux_platform.h @@ -103,6 +103,22 @@ struct scap_linux_platform struct scap_platform* scap_linux_alloc_platform(proc_entry_callback proc_callback, void* proc_callback_context); +/** + * @brief A lightweight Linux platform that only collects static host information + * + * This is useful with source plugins that do not handle syscall data but still want access + * to some info about the machine they're running on. Currently collected data includes: + * - machine info + * - agent info + * - interface list + */ +struct scap_linux_hostinfo_platform +{ + struct scap_platform m_generic; +}; + +struct scap_platform* scap_linux_hostinfo_alloc_platform(); + #ifdef __cplusplus }; #endif diff --git a/userspace/libscap/scap.c b/userspace/libscap/scap.c index 04a83aeaca..00a046df72 100644 --- a/userspace/libscap/scap.c +++ b/userspace/libscap/scap.c @@ -35,12 +35,16 @@ limitations under the License. // The test_input and source_plugin engines can optionally use a linux_platform // but only on an actual Linux system. // -// Still, to compile properly on non-Linux, provide an implementation -// of scap_linux_alloc_platform() that always fails at runtime. +// Still, to compile properly on non-Linux, provide implementations +// of scap_linux_alloc_platform() and scap_linux_hostinfo_alloc_platform() that always fail at runtime. struct scap_platform* scap_linux_alloc_platform(proc_entry_callback proc_callback, void* proc_callback_context) { return NULL; } +struct scap_platform* scap_linux_hostinfo_alloc_platform() +{ + return NULL; +} #endif const char* scap_getlasterr(scap_t* handle) diff --git a/userspace/libsinsp/sinsp.cpp b/userspace/libsinsp/sinsp.cpp index 86b722df41..f1d6458c00 100644 --- a/userspace/libsinsp/sinsp.cpp +++ b/userspace/libsinsp/sinsp.cpp @@ -553,7 +553,8 @@ void sinsp::open_savefile(const std::string& filename, int fd) #endif } -void sinsp::open_plugin(const std::string& plugin_name, const std::string& plugin_open_params, sinsp_mode_t mode) +void sinsp::open_plugin(const std::string& plugin_name, const std::string& plugin_open_params, + sinsp_plugin_platform platform_type) { #ifdef HAS_ENGINE_SOURCE_PLUGIN scap_open_args oargs {}; @@ -564,16 +565,23 @@ void sinsp::open_plugin(const std::string& plugin_name, const std::string& plugi oargs.engine_params = ¶ms; scap_platform* platform; - switch(mode) + sinsp_mode_t mode; + switch(platform_type) { - case SINSP_MODE_PLUGIN: - platform = scap_generic_alloc_platform(::on_new_entry_from_proc, this); - break; - case SINSP_MODE_LIVE: - platform = scap_linux_alloc_platform(::on_new_entry_from_proc, this); - break; - default: - throw sinsp_exception("Unsupported mode for SOURCE_PLUGIN engine"); + case sinsp_plugin_platform::SINSP_PLATFORM_GENERIC: + mode = SINSP_MODE_PLUGIN; + platform = scap_generic_alloc_platform(::on_new_entry_from_proc, this); + break; + case sinsp_plugin_platform::SINSP_PLATFORM_HOSTINFO: + mode = SINSP_MODE_PLUGIN; + platform = scap_linux_hostinfo_alloc_platform(); + break; + case sinsp_plugin_platform::SINSP_PLATFORM_FULL: + mode = SINSP_MODE_LIVE; + platform = scap_linux_alloc_platform(::on_new_entry_from_proc, this); + break; + default: + throw sinsp_exception("Unsupported mode for SOURCE_PLUGIN engine"); } open_common(&oargs, &scap_source_plugin_engine, platform, mode); #else diff --git a/userspace/libsinsp/sinsp.h b/userspace/libsinsp/sinsp.h index a709cc44a2..8e6d89a230 100644 --- a/userspace/libsinsp/sinsp.h +++ b/userspace/libsinsp/sinsp.h @@ -139,6 +139,16 @@ enum sinsp_mode_t SINSP_MODE_TEST, }; +/** + * @brief Possible platforms to use with plugins + */ +enum class sinsp_plugin_platform +{ + SINSP_PLATFORM_GENERIC, //!< generic platform, no system information collected + SINSP_PLATFORM_HOSTINFO, //!< basic host information collected, for non-syscall source plugins + SINSP_PLATFORM_FULL, //!< full system information collected, for syscall source plugins +}; + /** @defgroup inspector Main library @{ */ @@ -168,7 +178,7 @@ class SINSP_PUBLIC sinsp : public capture_stats_source virtual void open_nodriver(bool full_proc_scan = false); virtual void open_savefile(const std::string &filename, int fd = 0); virtual void open_plugin(const std::string& plugin_name, const std::string& plugin_open_params, - sinsp_mode_t mode = SINSP_MODE_PLUGIN); + sinsp_plugin_platform platform_type); virtual void open_gvisor(const std::string &config_path, const std::string &root_path, bool no_events = false, int epoll_timeout = -1); /*[EXPERIMENTAL] This API could change between releases, we are trying to find the right configuration to deploy the modern bpf probe: * `cpus_for_each_buffer` and `online_only` are the 2 experimental params. The first one allows associating more than one CPU to a single ring buffer. diff --git a/userspace/libsinsp/test/plugins.ut.cpp b/userspace/libsinsp/test/plugins.ut.cpp index 1821ddc35d..7f5535ebfb 100644 --- a/userspace/libsinsp/test/plugins.ut.cpp +++ b/userspace/libsinsp/test/plugins.ut.cpp @@ -273,7 +273,13 @@ TEST_F(sinsp_with_test_input, plugin_syscall_source) // we will not use the test scap engine here, but open the src plugin instead // note: we configure the plugin to just emit 1 event through its open params - m_inspector.open_plugin(src_pl->name(), "1"); + m_inspector.open_plugin(src_pl->name(), "1", sinsp_plugin_platform::SINSP_PLATFORM_HOSTINFO); + +#ifdef __linux__ + // The LINUX_HOSTINFO platform type fills in machine_info, but only on Linux + // (non-Linux platforms have a stub implementation in scap.c) + ASSERT_GT(m_inspector.get_machine_info()->num_cpus, 0); +#endif auto evt = next_event(); ASSERT_NE(evt, nullptr); @@ -310,7 +316,10 @@ TEST_F(sinsp_with_test_input, plugin_custom_source) // we will not use the test scap engine here, but open the src plugin instead // note: we configure the plugin to just emit 1 event through its open params - m_inspector.open_plugin(src_pl->name(), "1"); + m_inspector.open_plugin(src_pl->name(), "1", sinsp_plugin_platform::SINSP_PLATFORM_GENERIC); + + // the GENERIC platform type does not fill in machine_info + ASSERT_EQ(m_inspector.get_machine_info()->num_cpus, 0); auto evt = next_event(); ASSERT_NE(evt, nullptr);