From ef1fe3fc7eb09fc9a5c90c93d2f1082c1dc2f97d Mon Sep 17 00:00:00 2001 From: Mark Stemm Date: Thu, 13 Jun 2024 15:22:16 -0700 Subject: [PATCH] Modify evttype_index_ruleset to derive from indexable_ruleset Modify evttype_index_ruleset to derive from indexable_ruleset instead of having its own implementation of segregating filters by ruleset id/event type. An evttype_index_ruleset::wrapper contains a falco rule and filter, and run_wrappers() evaluate the filter as before, without the segregation by ruleset id/event type. Signed-off-by: Mark Stemm --- userspace/engine/evttype_index_ruleset.cpp | 365 ++------------------- userspace/engine/evttype_index_ruleset.h | 134 +------- 2 files changed, 53 insertions(+), 446 deletions(-) diff --git a/userspace/engine/evttype_index_ruleset.cpp b/userspace/engine/evttype_index_ruleset.cpp index 47e1891cd07..481df9b2b29 100644 --- a/userspace/engine/evttype_index_ruleset.cpp +++ b/userspace/engine/evttype_index_ruleset.cpp @@ -17,14 +17,14 @@ limitations under the License. #include "evttype_index_ruleset.h" -#include "falco_utils.h" - #include "logger.h" #include evttype_index_ruleset::evttype_index_ruleset( - std::shared_ptr f): m_filter_factory(f) + std::shared_ptr f): + indexable_ruleset(true), + m_filter_factory(f) { } @@ -32,170 +32,6 @@ evttype_index_ruleset::~evttype_index_ruleset() { } -evttype_index_ruleset::ruleset_filters::ruleset_filters() -{ -} - -evttype_index_ruleset::ruleset_filters::~ruleset_filters() -{ -} - -void evttype_index_ruleset::ruleset_filters::add_wrapper_to_list(filter_wrapper_list &wrappers, std::shared_ptr wrap) -{ - // This is O(n) but it's also uncommon - // (when loading rules only). - auto pos = std::find(wrappers.begin(), - wrappers.end(), - wrap); - - if(pos == wrappers.end()) - { - wrappers.push_back(wrap); - } -} - -void evttype_index_ruleset::ruleset_filters::remove_wrapper_from_list(filter_wrapper_list &wrappers, std::shared_ptr wrap) -{ - // This is O(n) but it's also uncommon - // (when loading rules only). - auto pos = std::find(wrappers.begin(), - wrappers.end(), - wrap); - if(pos != wrappers.end()) - { - wrappers.erase(pos); - } -} - -void evttype_index_ruleset::ruleset_filters::add_filter(std::shared_ptr wrap) -{ - if(wrap->event_codes.empty()) - { - // Should run for all event types - add_wrapper_to_list(m_filter_all_event_types, wrap); - } - else - { - for(auto &etype : wrap->event_codes) - { - if(m_filter_by_event_type.size() <= etype) - { - m_filter_by_event_type.resize(etype + 1); - } - - add_wrapper_to_list(m_filter_by_event_type[etype], wrap); - } - } - - m_filters.insert(wrap); -} - -void evttype_index_ruleset::ruleset_filters::remove_filter(std::shared_ptr wrap) -{ - if(wrap->event_codes.empty()) - { - remove_wrapper_from_list(m_filter_all_event_types, wrap); - } - else - { - for(auto &etype : wrap->event_codes) - { - if( etype < m_filter_by_event_type.size() ) - { - remove_wrapper_from_list(m_filter_by_event_type[etype], wrap); - } - } - } - - m_filters.erase(wrap); -} - -uint64_t evttype_index_ruleset::ruleset_filters::num_filters() -{ - return m_filters.size(); -} - -bool evttype_index_ruleset::ruleset_filters::run(sinsp_evt *evt, falco_rule& match) -{ - if(evt->get_type() < m_filter_by_event_type.size()) - { - for(const auto &wrap : m_filter_by_event_type[evt->get_type()]) - { - if(wrap->filter->run(evt)) - { - match = wrap->rule; - return true; - } - } - } - - // Finally, try filters that are not specific to an event type. - for(const auto &wrap : m_filter_all_event_types) - { - if(wrap->filter->run(evt)) - { - match = wrap->rule; - return true; - } - } - - return false; -} - -bool evttype_index_ruleset::ruleset_filters::run(sinsp_evt *evt, std::vector& matches) -{ - bool match_found = false; - - if(evt->get_type() < m_filter_by_event_type.size()) - { - for(const auto &wrap : m_filter_by_event_type[evt->get_type()]) - { - if(wrap->filter->run(evt)) - { - matches.push_back(wrap->rule); - match_found = true; - } - } - } - - if(match_found) - { - return true; - } - - // Finally, try filters that are not specific to an event type. - for(const auto &wrap : m_filter_all_event_types) - { - if(wrap->filter->run(evt)) - { - matches.push_back(wrap->rule); - match_found = true; - } - } - - return match_found; -} - -libsinsp::events::set evttype_index_ruleset::ruleset_filters::sc_codes() -{ - libsinsp::events::set res; - for(const auto &wrap : m_filters) - { - res.insert(wrap->sc_codes.begin(), wrap->sc_codes.end()); - } - return res; -} - -libsinsp::events::set evttype_index_ruleset::ruleset_filters::event_codes() -{ - libsinsp::events::set res; - for(const auto &wrap : m_filters) - { - res.insert(wrap->event_codes.begin(), wrap->event_codes.end()); - } - return res; -} - void evttype_index_ruleset::add( const falco_rule& rule, std::shared_ptr filter, @@ -203,21 +39,22 @@ void evttype_index_ruleset::add( { try { - auto wrap = std::make_shared(); - wrap->rule = rule; - wrap->filter = filter; + auto wrap = std::make_shared(); + wrap->m_rule = rule; + wrap->m_filter = filter; if(rule.source == falco_common::syscall_source) { - wrap->sc_codes = libsinsp::filter::ast::ppm_sc_codes(condition.get()); - wrap->event_codes = libsinsp::filter::ast::ppm_event_codes(condition.get()); + wrap->m_sc_codes = libsinsp::filter::ast::ppm_sc_codes(condition.get()); + wrap->m_event_codes = libsinsp::filter::ast::ppm_event_codes(condition.get()); } else { - wrap->sc_codes = { }; - wrap->event_codes = { ppm_event_code::PPME_PLUGINEVENT_E }; + wrap->m_sc_codes = {}; + wrap->m_event_codes = {ppm_event_code::PPME_PLUGINEVENT_E}; } - wrap->event_codes.insert(ppm_event_code::PPME_ASYNCEVENT_E); - m_filters.insert(wrap); + wrap->m_event_codes.insert(ppm_event_code::PPME_ASYNCEVENT_E); + + add_wrapper(wrap); } catch (const sinsp_exception& e) { @@ -230,180 +67,48 @@ void evttype_index_ruleset::on_loading_complete() print_enabled_rules_falco_logger(); } -void evttype_index_ruleset::print_enabled_rules_falco_logger() -{ - falco_logger::log(falco_logger::level::DEBUG, "Enabled rules:\n"); - int n = 0; - for (const auto& ruleset_ptr : m_rulesets) - { - if (ruleset_ptr) - { - for (const auto& wrap : ruleset_ptr->get_filters()) - { - n++; - falco_logger::log(falco_logger::level::DEBUG, std::string(" ") + wrap->rule.name + "\n"); - } - } - } - falco_logger::log(falco_logger::level::DEBUG, "(" + std::to_string(n) + ") enabled rules in total\n"); -} - -void evttype_index_ruleset::clear() -{ - for (size_t i = 0; i < m_rulesets.size(); i++) - { - m_rulesets[i] = std::make_shared(); - } - m_filters.clear(); -} - -void evttype_index_ruleset::enable(const std::string &pattern, match_type match, uint16_t ruleset_id) -{ - enable_disable(pattern, match, true, ruleset_id); -} - -void evttype_index_ruleset::disable(const std::string &pattern, match_type match, uint16_t ruleset_id) +bool evttype_index_ruleset::run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, falco_rule &match) { - enable_disable(pattern, match, false, ruleset_id); -} - -void evttype_index_ruleset::enable_disable(const std::string &pattern, match_type match, bool enabled, uint16_t ruleset_id) -{ - while(m_rulesets.size() < (size_t)ruleset_id + 1) + for(auto &wrap : wrappers) { - m_rulesets.emplace_back(std::make_shared()); - } - - for(const auto &wrap : m_filters) - { - bool matches; - std::string::size_type pos; - - switch(match) + std::shared_ptr derived = std::dynamic_pointer_cast(wrap); + if(derived->m_filter->run(evt)) { - case match_type::exact: - pos = wrap->rule.name.find(pattern); - - matches = (pattern == "" || (pos == 0 && - pattern.size() == wrap->rule.name.size())); - break; - case match_type::substring: - matches = (pattern == "" || (wrap->rule.name.find(pattern) != std::string::npos)); - break; - case match_type::wildcard: - matches = falco::utils::matches_wildcard(pattern, wrap->rule.name); - break; - default: - // should never happen - matches = false; - } - - if(matches) - { - if(enabled) - { - m_rulesets[ruleset_id]->add_filter(wrap); - } - else - { - m_rulesets[ruleset_id]->remove_filter(wrap); - } + match = derived->m_rule; + return true; } } -} - -void evttype_index_ruleset::enable_tags(const std::set &tags, uint16_t ruleset_id) -{ - enable_disable_tags(tags, true, ruleset_id); -} -void evttype_index_ruleset::disable_tags(const std::set &tags, uint16_t ruleset_id) -{ - enable_disable_tags(tags, false, ruleset_id); + return false; } -void evttype_index_ruleset::enable_disable_tags(const std::set &tags, bool enabled, uint16_t ruleset_id) +bool evttype_index_ruleset::run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, std::vector &matches) { - while(m_rulesets.size() < (size_t)ruleset_id + 1) - { - m_rulesets.emplace_back(std::make_shared()); - } + bool match_found = false; - for(const auto &wrap : m_filters) + for(auto &wrap : wrappers) { - std::set intersect; - - set_intersection(tags.begin(), tags.end(), - wrap->rule.tags.begin(), wrap->rule.tags.end(), - inserter(intersect, intersect.begin())); - - if(!intersect.empty()) + std::shared_ptr derived = std::dynamic_pointer_cast(wrap); + if(derived->m_filter->run(evt)) { - if(enabled) - { - m_rulesets[ruleset_id]->add_filter(wrap); - } - else - { - m_rulesets[ruleset_id]->remove_filter(wrap); - } + matches.push_back(derived->m_rule); + match_found = true; } } -} - -uint64_t evttype_index_ruleset::enabled_count(uint16_t ruleset_id) -{ - while(m_rulesets.size() < (size_t)ruleset_id + 1) - { - m_rulesets.emplace_back(std::make_shared()); - } - - return m_rulesets[ruleset_id]->num_filters(); -} - -bool evttype_index_ruleset::run(sinsp_evt *evt, falco_rule& match, uint16_t ruleset_id) -{ - if(m_rulesets.size() < (size_t)ruleset_id + 1) - { - return false; - } - return m_rulesets[ruleset_id]->run(evt, match); + return match_found; } -bool evttype_index_ruleset::run(sinsp_evt *evt, std::vector& matches, uint16_t ruleset_id) +void evttype_index_ruleset::print_enabled_rules_falco_logger() { - if(m_rulesets.size() < (size_t)ruleset_id + 1) - { - return false; - } - - return m_rulesets[ruleset_id]->run(evt, matches); -} + falco_logger::log(falco_logger::level::DEBUG, "Enabled rules:\n"); -void evttype_index_ruleset::enabled_evttypes(std::set &evttypes, uint16_t ruleset_id) -{ - evttypes.clear(); - for (const auto& e : enabled_event_codes(ruleset_id)) + auto logger = [](std::shared_ptr wrap) { - evttypes.insert((uint16_t) e); - } -} + falco_logger::log(falco_logger::level::DEBUG, std::string(" ") + wrap->name() + "\n"); + }; -libsinsp::events::set evttype_index_ruleset::enabled_sc_codes(uint16_t ruleset) -{ - if(m_rulesets.size() < (size_t)ruleset + 1) - { - return {}; - } - return m_rulesets[ruleset]->sc_codes(); -} + uint64_t num_filters = iterate(logger); -libsinsp::events::set evttype_index_ruleset::enabled_event_codes(uint16_t ruleset) -{ - if(m_rulesets.size() < (size_t)ruleset + 1) - { - return {}; - } - return m_rulesets[ruleset]->event_codes(); + falco_logger::log(falco_logger::level::DEBUG, "(" + std::to_string(num_filters) + ") enabled rules in total\n"); } diff --git a/userspace/engine/evttype_index_ruleset.h b/userspace/engine/evttype_index_ruleset.h index 01ac4e3000c..d0feaa0d918 100644 --- a/userspace/engine/evttype_index_ruleset.h +++ b/userspace/engine/evttype_index_ruleset.h @@ -17,151 +17,53 @@ limitations under the License. #pragma once +#include "indexable_ruleset.h" + #include #include #include -#include -#include - -#include "filter_ruleset.h" -#include -#include -#include /*! \brief A filter_ruleset that indexes enabled rules by event type, and performs linear search on each event type bucket */ -class evttype_index_ruleset: public filter_ruleset +class evttype_index_ruleset : public indexable_ruleset { public: explicit evttype_index_ruleset(std::shared_ptr factory); virtual ~evttype_index_ruleset(); + // From filter_ruleset void add( const falco_rule& rule, std::shared_ptr filter, std::shared_ptr condition) override; - void clear() override; - - bool run(sinsp_evt *evt, falco_rule& match, uint16_t ruleset_id) override; - bool run(sinsp_evt *evt, std::vector&matches, uint16_t ruleset_id) override; - - uint64_t enabled_count(uint16_t ruleset_id) override; - void on_loading_complete() override; + // From indexable_ruleset + bool run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, falco_rule &match) override; + bool run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, std::vector &matches) override; + // Print each enabled rule when running Falco with falco logger // log_level=debug; invoked within on_loading_complete() void print_enabled_rules_falco_logger(); - void enable( - const std::string &pattern, - match_type match, - uint16_t rulset_id) override; - - void disable( - const std::string &pattern, - match_type match, - uint16_t rulset_id) override; - - void enable_tags( - const std::set &tags, - uint16_t rulset_id) override; - - void disable_tags( - const std::set &tags, - uint16_t rulset_id) override; - - // note(jasondellaluce): this is deprecated, must use the new - // typing-improved `enabled_event_codes` and `enabled_sc_codes` instead - // todo(jasondellaluce): remove this in future code refactors - void enabled_evttypes( - std::set &evttypes, - uint16_t ruleset) override; - - libsinsp::events::set enabled_sc_codes(uint16_t ruleset) override; - - libsinsp::events::set enabled_event_codes(uint16_t ruleset) override; - private: - - // Helper used by enable()/disable() - void enable_disable( - const std::string &pattern, - match_type match, - bool enabled, - uint16_t rulset_id); - - // Helper used by enable_tags()/disable_tags() - void enable_disable_tags( - const std::set &tags, - bool enabled, - uint16_t rulset_id); - - struct filter_wrapper + struct wrapper : public indexable_ruleset::filter_wrapper { - falco_rule rule; - libsinsp::events::set sc_codes; - libsinsp::events::set event_codes; - std::shared_ptr filter; + const std::string &name() override { return m_rule.name; } + const std::set &tags() override { return m_rule.tags; } + const libsinsp::events::set &sc_codes() override { return m_sc_codes; } + const libsinsp::events::set &event_codes() override { return m_event_codes; } + + falco_rule m_rule; + libsinsp::events::set m_sc_codes; + libsinsp::events::set m_event_codes; + std::shared_ptr m_filter; }; - typedef std::list> filter_wrapper_list; - - // A group of filters all having the same ruleset - class ruleset_filters { - public: - ruleset_filters(); - - virtual ~ruleset_filters(); - - void add_filter(std::shared_ptr wrap); - void remove_filter(std::shared_ptr wrap); - - uint64_t num_filters(); - - inline const std::set>& get_filters() const - { - return m_filters; - } - - // Evaluate an event against the ruleset and return the first rule - // that matched. - bool run(sinsp_evt *evt, falco_rule& match); - - // Evaluate an event against the ruleset and return all the - // matching rules. - bool run(sinsp_evt *evt, std::vector& matches); - - libsinsp::events::set sc_codes(); - - libsinsp::events::set event_codes(); - - private: - void add_wrapper_to_list(filter_wrapper_list &wrappers, std::shared_ptr wrap); - void remove_wrapper_from_list(filter_wrapper_list &wrappers, std::shared_ptr wrap); - - // Vector indexes from event type to a set of filters. There can - // be multiple filters for a given event type. - // NOTE: This is used only when the event sub-type is 0. - std::vector m_filter_by_event_type; - - filter_wrapper_list m_filter_all_event_types; - - // All filters added. Used to make num_filters() fast. - std::set> m_filters; - }; - - // Vector indexes from ruleset id to set of rules. - std::vector> m_rulesets; - - // All filters added. The set of enabled filters is held in m_rulesets - std::set> m_filters; - std::shared_ptr m_filter_factory; - std::vector m_ruleset_names; }; class evttype_index_ruleset_factory: public filter_ruleset_factory