diff --git a/userspace/engine/evttype_index_ruleset.cpp b/userspace/engine/evttype_index_ruleset.cpp index 04aef217..31b6be56 100644 --- a/userspace/engine/evttype_index_ruleset.cpp +++ b/userspace/engine/evttype_index_ruleset.cpp @@ -160,10 +160,17 @@ void evttype_index_ruleset::add( sinsp_filter_compiler compiler(m_filter_factory, condition.get()); shared_ptr filter(compiler.compile()); std::shared_ptr wrap(new filter_wrapper()); - filter_evttype_resolver resolver; wrap->rule = rule; wrap->filter = filter; - resolver.evttypes(condition, wrap->evttypes); + if(rule.source == falco_common::syscall_source) + { + filter_evttype_resolver resolver; + resolver.evttypes(condition, wrap->evttypes); + } + else + { + wrap->evttypes = { ppm_event_type::PPME_PLUGINEVENT_E }; + } m_filters.insert(wrap); } catch (const sinsp_exception& e) diff --git a/userspace/engine/falco_engine.cpp b/userspace/engine/falco_engine.cpp index 0f8726d7..44aeb53b 100644 --- a/userspace/engine/falco_engine.cpp +++ b/userspace/engine/falco_engine.cpp @@ -169,7 +169,7 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events, uint64_t &required_engine_version) { rule_loader::configuration cfg(rules_content); - cfg.engine = this; + cfg.sources = m_sources; cfg.min_priority = m_min_priority; cfg.output_extra = m_extra; cfg.replace_output_container_info = m_replace_container_info; @@ -179,7 +179,10 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al bool success = reader.load(cfg, m_rule_loader); if (success) { - clear_filters(); + for (auto &s : m_sources) + { + s.ruleset->clear(); + } m_rules.clear(); success = m_rule_loader.compile(cfg, m_rules); } diff --git a/userspace/engine/rule_loader.cpp b/userspace/engine/rule_loader.cpp index 1d55ceca..103aacfc 100644 --- a/userspace/engine/rule_loader.cpp +++ b/userspace/engine/rule_loader.cpp @@ -48,22 +48,6 @@ static void paren_item(string& e) } } -static bool is_field_defined( - falco_engine *engine, const string& source, string field) -{ - auto factory = engine->get_filter_factory(source); - if(factory) - { - auto *chk = factory->new_filtercheck(field.c_str()); - if (chk) - { - delete(chk); - return true; - } - } - return false; -} - static inline bool is_operator_defined(const string& op) { auto ops = libsinsp::filter::parser::supported_operators(); @@ -76,13 +60,12 @@ static inline bool is_operator_for_list(const string& op) return find(ops.begin(), ops.end(), op) != ops.end(); } -static bool is_format_valid( - falco_engine* e, const string& src, const string& fmt, string& err) +static bool is_format_valid(const falco_source& source, string fmt, string& err) { try { shared_ptr formatter; - formatter = e->create_formatter(src, fmt); + formatter = source.formatter_factory->create_formatter(fmt); return true; } catch(exception &e) @@ -118,9 +101,8 @@ static inline void append_info(T* prev, T& info, uint32_t id) } static void validate_exception_info( - rule_loader::configuration& cfg, - rule_loader::rule_exception_info &ex, - const string& source) + const falco_source& source, + rule_loader::rule_exception_info &ex) { if (ex.fields.is_list) { @@ -133,7 +115,7 @@ static void validate_exception_info( } } THROW(ex.fields.items.size() != ex.comps.items.size(), - "Rule exception item " + ex.name + "Rule exception item " + ex.name + ": fields and comps lists must have equal length"); for (auto &v : ex.comps.items) { @@ -143,7 +125,7 @@ static void validate_exception_info( } for (auto &v : ex.fields.items) { - THROW(!is_field_defined(cfg.engine, source, v.item), + THROW(!source.is_field_defined(v.item), "Rule exception item " + ex.name + ": field name " + v.item + " is not a supported filter field"); } @@ -160,7 +142,7 @@ static void validate_exception_info( THROW(!is_operator_defined(ex.comps.item), "Rule exception item " + ex.name + ": comparison operator " + ex.comps.item + " is not a supported comparison operator"); - THROW(!is_field_defined(cfg.engine, source, ex.fields.item), + THROW(!source.is_field_defined(ex.fields.item), "Rule exception item " + ex.name + ": field name " + ex.fields.item + " is not a supported filter field"); } @@ -365,37 +347,11 @@ static shared_ptr parse_condition( } catch (const sinsp_exception& e) { - throw falco_exception("Compilation error when compiling \"" + throw falco_exception("Compilation error when compiling \"" + condition + "\": " + to_string(p.get_pos().col) + ": " + e.what()); } } -static shared_ptr compile_condition( - falco_engine* engine, - uint32_t id, - shared_ptr cnd, - string src, - string& err) -{ - try - { - auto factory = engine->get_filter_factory(src); - sinsp_filter_compiler compiler(factory, cnd.get()); - compiler.set_check_id(id); - shared_ptr ret(compiler.compile()); - return ret; - } - catch (const sinsp_exception& e) - { - err = e.what(); - } - catch (const falco_exception& e) - { - err = e.what(); - } - return nullptr; -} - static void apply_output_substitutions( rule_loader::configuration& cfg, string& out) @@ -457,7 +413,7 @@ void rule_loader::append(configuration& cfg, list_info& info) void rule_loader::define(configuration& cfg, macro_info& info) { - if (!cfg.engine->is_source_valid(info.source)) + if (!cfg.sources.at(info.source)) { cfg.warnings.push_back("Macro " + info.name + ": warning (unknown-source): unknown source " @@ -484,7 +440,8 @@ void rule_loader::append(configuration& cfg, macro_info& info) void rule_loader::define(configuration& cfg, rule_info& info) { - if (!cfg.engine->is_source_valid(info.source)) + auto source = cfg.sources.at(info.source); + if (!source) { cfg.warnings.push_back("Rule " + info.name + ": warning (unknown-source): unknown source " @@ -500,7 +457,7 @@ void rule_loader::define(configuration& cfg, rule_info& info) { THROW(!ex.fields.is_valid(), "Rule exception item " + ex.name + ": must have fields property with a list of fields"); - validate_exception_info(cfg, ex, info.source); + validate_exception_info(*source, ex); } define_info(m_rule_infos, info, m_cur_index++); @@ -514,6 +471,11 @@ void rule_loader::append(configuration& cfg, rule_info& info) THROW(info.cond.empty() && info.exceptions.empty(), "Appended rule must have exceptions or condition property"); + auto source = cfg.sources.at(prev->source); + // note: this is not supposed to happen + THROW(!source, "Rule " + prev->name + + ": error (unknown-source): unknown source " + prev->source); + if (!info.cond.empty()) { prev->cond += " "; @@ -531,7 +493,7 @@ void rule_loader::append(configuration& cfg, rule_info& info) + ex.name + ": must have fields property with a list of fields"); THROW(ex.values.empty(), "Rule exception new item " + ex.name + ": must have fields property with a list of values"); - validate_exception_info(cfg, ex, prev->source); + validate_exception_info(*source, ex); prev->exceptions.push_back(ex); } else @@ -649,9 +611,15 @@ void rule_loader::compile_rule_infos( continue; } + auto source = cfg.sources.at(r.source); + // note: this is not supposed to happen + THROW(!source, "Rule " + r.name + + ": error (unknown-source): unknown source " + r.source); + // build filter AST by parsing the condition, building exceptions, // and resolving lists and macros falco_rule rule; + condition = r.cond; if (!r.exceptions.empty()) { @@ -679,7 +647,8 @@ void rule_loader::compile_rule_infos( { apply_output_substitutions(cfg, rule.output); } - THROW(!is_format_valid(cfg.engine, r.source, rule.output, err), + + THROW(!is_format_valid(cfg.engine, r.source, rule.output, err), "Invalid output format '" + rule.output + "': '" + err + "'"); // construct rule definition and compile it to a filter @@ -688,13 +657,18 @@ void rule_loader::compile_rule_infos( rule.description = r.desc; rule.priority = r.priority; rule.tags = r.tags; - // note: indexes are 0-based, but 0 is not an acceptable rule_id - auto id = out.insert(rule, rule.name) + 1; - auto filter = compile_condition(cfg.engine, id, ast, rule.source, err); - if (!filter) + try { - if (r.skip_if_unknown_filter - && err.find("nonexistent field") != string::npos) + auto rule_id = out.insert(rule, rule.name); + out.at(rule_id)->id = rule_id; + source->ruleset->add(*out.at(rule_id), ast); + source->ruleset->enable(rule.name, false, r.enabled); + } + catch (falco_exception& e) + { + string err = e.what(); + if (err.find("nonexistent field") != string::npos + && r.skip_if_unknown_filter) { cfg.warnings.push_back( "Rule " + rule.name + ": warning (unknown-field):"); @@ -705,7 +679,7 @@ void rule_loader::compile_rule_infos( throw falco_exception("Rule " + rule.name + ": error " + err); } } - + // populate set of event types and emit an special warning set evttypes = { ppm_event_type::PPME_PLUGINEVENT_E }; if(rule.source == falco_common::syscall_source) @@ -721,10 +695,6 @@ void rule_loader::compile_rule_infos( + " This has a significant performance penalty."); } } - - // add rule and its filter in the engine - cfg.engine->add_filter(filter, rule.name, rule.source, evttypes, rule.tags); - cfg.engine->enable_rule(rule.name, r.enabled); } catch (exception& e) { @@ -769,4 +739,4 @@ bool rule_loader::compile(configuration& cfg, indexed_vector& out) c } } return true; -} \ No newline at end of file +} diff --git a/userspace/engine/rule_loader.h b/userspace/engine/rule_loader.h index 29c88eac..57964da3 100644 --- a/userspace/engine/rule_loader.h +++ b/userspace/engine/rule_loader.h @@ -21,11 +21,9 @@ limitations under the License. #include #include #include "falco_rule.h" +#include "falco_source.h" #include "indexed_vector.h" -// todo(jasondellaluce): remove this cyclic dependency -class falco_engine; - /*! \brief Ruleset loader of the falco engine @@ -73,9 +71,9 @@ public: std::string output_extra; bool replace_output_container_info; falco_common::priority_type min_priority; + indexed_vector sources; std::vector warnings; std::vector errors; - falco_engine* engine; }; /*! diff --git a/userspace/engine/ruleset.h b/userspace/engine/ruleset.h index edd163f5..33bdb273 100644 --- a/userspace/engine/ruleset.h +++ b/userspace/engine/ruleset.h @@ -16,11 +16,11 @@ limitations under the License. #pragma once +#include "falco_rule.h" +#include #include #include #include -#include -#include "falco_rule.h" /*! \brief Represents a manager for rulesets.A ruleset represents a set of