From 27679b178f9850ebf359843bd1ba7e6027754c2f Mon Sep 17 00:00:00 2001 From: Grzegorz Nosek Date: Thu, 12 Dec 2024 07:12:40 +0100 Subject: [PATCH] fix(runner): match event source name properly (not plugin name) Signed-off-by: Grzegorz Nosek --- falco_plugin_runner/src/plugin/mod.rs | 17 +- .../tests/dummy_syscall_source.rs | 148 ++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 falco_plugin_tests/tests/dummy_syscall_source.rs diff --git a/falco_plugin_runner/src/plugin/mod.rs b/falco_plugin_runner/src/plugin/mod.rs index 48f6e4fc..cd962ab8 100644 --- a/falco_plugin_runner/src/plugin/mod.rs +++ b/falco_plugin_runner/src/plugin/mod.rs @@ -132,6 +132,21 @@ impl Plugin { } } + pub fn source_name(&self) -> *const c_char { + if let Some(get_source) = self.api().__bindgen_anon_1.get_event_source { + let ptr = unsafe { get_source() }; + if !ptr.is_null() { + let source = unsafe { CStr::from_ptr(ptr) }; + if !source.is_empty() { + return ptr; + } + return c"syscall".as_ptr(); + } + } + + std::ptr::null() + } + pub fn last_error(&self) -> Option { let get_last_error = self.api().get_last_error?; let last_error = unsafe { get_last_error(self.plugin) }; @@ -385,7 +400,7 @@ impl Plugin { fn decorate_event(&mut self, buf: *mut ss_plugin_event) -> Event { Event { - source: self.name(), + source: self.source_name(), source_plugin: self.plugin, to_string: self.api.__bindgen_anon_1.event_to_string, buf, diff --git a/falco_plugin_tests/tests/dummy_syscall_source.rs b/falco_plugin_tests/tests/dummy_syscall_source.rs new file mode 100644 index 00000000..846b7692 --- /dev/null +++ b/falco_plugin_tests/tests/dummy_syscall_source.rs @@ -0,0 +1,148 @@ +use falco_plugin::anyhow::Error; +use falco_plugin::base::Plugin; +use falco_plugin::event::events::types::{EventType, PPME_GENERIC_E}; +use falco_plugin::event::events::{Event, EventMetadata}; +use falco_plugin::event::fields::types::PT_SYSCALLID; +use falco_plugin::extract::{field, ExtractFieldInfo, ExtractPlugin, ExtractRequest}; +use falco_plugin::source::{EventBatch, EventInput, SourcePlugin, SourcePluginInstance}; +use falco_plugin::tables::TablesInput; +use falco_plugin::{anyhow, static_plugin}; +use std::ffi::{CStr, CString}; + +struct DummyPlugin; + +impl Plugin for DummyPlugin { + const NAME: &'static CStr = c"dummy"; + const PLUGIN_VERSION: &'static CStr = c"0.0.0"; + const DESCRIPTION: &'static CStr = c"dummy no-op plugin"; + const CONTACT: &'static CStr = c"rust@localdomain.pl"; + type ConfigType = String; + + fn new(_input: Option<&TablesInput>, config: Self::ConfigType) -> Result { + log::set_max_level(log::LevelFilter::Trace); + if config != "testing" { + anyhow::bail!("I only accept \"testing\" as the config string"); + } + + Ok(Self) + } + + fn set_config(&mut self, config: Self::ConfigType) -> Result<(), Error> { + if config != "testing" { + anyhow::bail!("I only accept \"testing\" as the config string, even in an update"); + } + + Ok(()) + } +} + +struct DummyPluginInstance; + +impl SourcePluginInstance for DummyPluginInstance { + type Plugin = DummyPlugin; + + fn next_batch( + &mut self, + _plugin: &mut Self::Plugin, + batch: &mut EventBatch, + ) -> Result<(), Error> { + batch.add(Event { + metadata: EventMetadata { ts: 0, tid: 1 }, + params: PPME_GENERIC_E { + id: Some(PT_SYSCALLID(1)), + native_id: Some(1), + }, + })?; + + Ok(()) + } +} + +impl SourcePlugin for DummyPlugin { + type Instance = DummyPluginInstance; + const EVENT_SOURCE: &'static CStr = c""; + const PLUGIN_ID: u32 = 0; + + fn open(&mut self, _params: Option<&str>) -> Result { + Ok(DummyPluginInstance) + } + + fn event_to_string(&mut self, _event: &EventInput) -> Result { + Ok(CString::from(c"what event?")) + } +} + +struct DummyExtractPlugin; + +impl Plugin for DummyExtractPlugin { + const NAME: &'static CStr = c"dummy-extract"; + const PLUGIN_VERSION: &'static CStr = c"0.0.0"; + const DESCRIPTION: &'static CStr = c"dummy extract plugin"; + const CONTACT: &'static CStr = c"rust@localdomain.pl"; + type ConfigType = (); + + fn new(_input: Option<&TablesInput>, _config: Self::ConfigType) -> Result { + Ok(Self) + } + + fn set_config(&mut self, _config: Self::ConfigType) -> Result<(), Error> { + Ok(()) + } +} +impl DummyExtractPlugin { + fn extract_tid(&mut self, req: ExtractRequest) -> Result { + let event = req.event.event()?; + Ok(event.metadata.tid as u64) + } +} + +impl ExtractPlugin for DummyExtractPlugin { + const EVENT_TYPES: &'static [EventType] = &[]; + const EVENT_SOURCES: &'static [&'static str] = &["syscall"]; + type ExtractContext = (); + const EXTRACT_FIELDS: &'static [ExtractFieldInfo] = + &[field("dummy.tid", &Self::extract_tid)]; +} + +static_plugin!(DUMMY_PLUGIN_API = DummyPlugin); +static_plugin!(EXTRACT_PLUGIN_API = DummyExtractPlugin); + +#[cfg(test)] +mod tests { + use falco_plugin::base::Plugin; + use falco_plugin_tests::{init_plugin, instantiate_tests, CapturingTestDriver, TestDriver}; + + fn test_dummy_init() { + init_plugin::(&super::DUMMY_PLUGIN_API, c"testing").unwrap(); + } + + fn test_dummy_init_bad_config() { + let res = init_plugin::(&super::DUMMY_PLUGIN_API, c"not testing"); + let res = res.unwrap_err().to_string(); + assert!(res.contains("I only accept \"testing\" as the config string")); + } + + fn test_dummy_next() { + let (mut driver, _plugin) = init_plugin::(&super::DUMMY_PLUGIN_API, c"testing").unwrap(); + let plugin = driver + .register_plugin(&super::EXTRACT_PLUGIN_API, c"") + .unwrap(); + driver.add_filterchecks(&plugin, c"syscall").unwrap(); + + let mut driver = driver.start_capture(super::DummyPlugin::NAME, c"").unwrap(); + + let event = driver.next_event().unwrap(); + assert_eq!( + driver + .event_field_as_string(c"dummy.tid", &event) + .unwrap() + .unwrap(), + "1" + ) + } + + instantiate_tests!( + test_dummy_init; + test_dummy_init_bad_config; + test_dummy_next); +}