diff --git a/cmake/modules/falcosecurity-libs.cmake b/cmake/modules/falcosecurity-libs.cmake index 60343c9b9a0..a7927ae5807 100644 --- a/cmake/modules/falcosecurity-libs.cmake +++ b/cmake/modules/falcosecurity-libs.cmake @@ -24,8 +24,8 @@ else() # default below In case you want to test against another falcosecurity/libs version just pass the variable - ie., `cmake # -DFALCOSECURITY_LIBS_VERSION=dev ..` if(NOT FALCOSECURITY_LIBS_VERSION) - set(FALCOSECURITY_LIBS_VERSION "b19f87e8aee663e4987a3db54570725e071ed105") - set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=fd5888588796bf52848cf75434784770e61d9a79f344bf571fe495b61e92ddd3") + set(FALCOSECURITY_LIBS_VERSION "d6b75db133602dee81b4408902f2510275feae57") + set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=396f784924d2916431ecfbfcd3732cc328f29c543c7cf5a917053f634ef6f7d4") endif() # cd /path/to/build && cmake /path/to/source diff --git a/tests/engine/test_filter_evttype_resolver.cpp b/tests/engine/test_filter_evttype_resolver.cpp index fa0187deb1a..e4041027b8d 100644 --- a/tests/engine/test_filter_evttype_resolver.cpp +++ b/tests/engine/test_filter_evttype_resolver.cpp @@ -38,8 +38,7 @@ string to_string(set s) void compare_evttypes(ast::expr* f, set &expected) { set actual; - filter_evttype_resolver resolver; - resolver.evttypes(f, actual); + filter_evttype_resolver().evttypes(f, actual); for(auto &etype : expected) { REQUIRE(actual.find(etype) != actual.end()); @@ -52,13 +51,11 @@ void compare_evttypes(ast::expr* f, set &expected) ast::expr* compile(const string &fltstr) { - libsinsp::filter::parser p(fltstr); - return p.parse(); + return libsinsp::filter::parser(fltstr).parse(); } TEST_CASE("Should find event types from filter", "[rule_loader]") { - filter_evttype_resolver resolver; set openat_only{ PPME_SYSCALL_OPENAT_2_E, PPME_SYSCALL_OPENAT_2_X }; diff --git a/userspace/engine/filter_evttype_resolver.cpp b/userspace/engine/filter_evttype_resolver.cpp index 6934a41fdaf..911f2416df1 100644 --- a/userspace/engine/filter_evttype_resolver.cpp +++ b/userspace/engine/filter_evttype_resolver.cpp @@ -27,7 +27,7 @@ static bool is_evttype_operator(const string& op) return op == "==" || op == "=" || op == "!=" || op == "in"; } -void filter_evttype_resolver::inversion(set& types) +void filter_evttype_resolver::visitor::inversion(set& types) { set all_types; evttypes("", all_types); @@ -41,7 +41,7 @@ void filter_evttype_resolver::inversion(set& types) } } -void filter_evttype_resolver::evttypes(string evtname, set& out) +void filter_evttype_resolver::visitor::evttypes(string evtname, set& out) { // Fill in from 2 to PPM_EVENT_MAX-1. 0 and 1 are excluded as // those are PPM_GENERIC_E/PPME_GENERIC_X @@ -58,26 +58,31 @@ void filter_evttype_resolver::evttypes(string evtname, set& out) } } -void filter_evttype_resolver::evttypes(ast::expr* filter, set& out) +void filter_evttype_resolver::evttypes( + ast::expr* filter, + set& out) const { - m_expect_value = false; - m_last_node_evttypes.clear(); - filter->accept(this); - out.insert(m_last_node_evttypes.begin(), m_last_node_evttypes.end()); + visitor v; + v.m_expect_value = false; + v.m_last_node_evttypes.clear(); + filter->accept(&v); + out.insert(v.m_last_node_evttypes.begin(), v.m_last_node_evttypes.end()); } void filter_evttype_resolver::evttypes( - shared_ptr filter, set& out) + shared_ptr filter, + set& out) const { - m_expect_value = false; - m_last_node_evttypes.clear(); - filter.get()->accept(this); - out.insert(m_last_node_evttypes.begin(), m_last_node_evttypes.end()); + visitor v; + v.m_expect_value = false; + v.m_last_node_evttypes.clear(); + filter.get()->accept(&v); + out.insert(v.m_last_node_evttypes.begin(), v.m_last_node_evttypes.end()); } // "and" nodes evttypes are the intersection of the evttypes of their children. // we initialize the set with "all event types" -void filter_evttype_resolver::visit(ast::and_expr* e) +void filter_evttype_resolver::visitor::visit(ast::and_expr* e) { set types, inters; evttypes("", types); @@ -96,7 +101,7 @@ void filter_evttype_resolver::visit(ast::and_expr* e) } // "or" nodes evttypes are the union of the evttypes their children -void filter_evttype_resolver::visit(ast::or_expr* e) +void filter_evttype_resolver::visitor::visit(ast::or_expr* e) { set types; m_last_node_evttypes.clear(); @@ -108,14 +113,14 @@ void filter_evttype_resolver::visit(ast::or_expr* e) m_last_node_evttypes = types; } -void filter_evttype_resolver::visit(ast::not_expr* e) +void filter_evttype_resolver::visitor::visit(ast::not_expr* e) { m_last_node_evttypes.clear(); e->child->accept(this); inversion(m_last_node_evttypes); } -void filter_evttype_resolver::visit(ast::binary_check_expr* e) +void filter_evttype_resolver::visitor::visit(ast::binary_check_expr* e) { m_last_node_evttypes.clear(); if (e->field == "evt.type" && is_evttype_operator(e->op)) @@ -132,13 +137,13 @@ void filter_evttype_resolver::visit(ast::binary_check_expr* e) evttypes("", m_last_node_evttypes); } -void filter_evttype_resolver::visit(ast::unary_check_expr* e) +void filter_evttype_resolver::visitor::visit(ast::unary_check_expr* e) { m_last_node_evttypes.clear(); evttypes("", m_last_node_evttypes); } -void filter_evttype_resolver::visit(ast::value_expr* e) +void filter_evttype_resolver::visitor::visit(ast::value_expr* e) { m_last_node_evttypes.clear(); if (m_expect_value) @@ -149,7 +154,7 @@ void filter_evttype_resolver::visit(ast::value_expr* e) evttypes("", m_last_node_evttypes); } -void filter_evttype_resolver::visit(ast::list_expr* e) +void filter_evttype_resolver::visitor::visit(ast::list_expr* e) { m_last_node_evttypes.clear(); if (m_expect_value) diff --git a/userspace/engine/filter_evttype_resolver.h b/userspace/engine/filter_evttype_resolver.h index 57401861078..10b5a45a6f2 100644 --- a/userspace/engine/filter_evttype_resolver.h +++ b/userspace/engine/filter_evttype_resolver.h @@ -24,7 +24,7 @@ limitations under the License. /*! \brief Helper class for finding event types */ -class filter_evttype_resolver: private libsinsp::filter::ast::expr_visitor +class filter_evttype_resolver { public: /*! @@ -35,7 +35,10 @@ class filter_evttype_resolver: private libsinsp::filter::ast::expr_visitor string is passed, all the available evttypes are collected \param out The set to be filled with the evttypes */ - void evttypes(std::string evtname, std::set& out); + inline void evttypes(std::string evtname, std::set& out) const + { + visitor().evttypes(evtname, out); + } /*! \brief Visits a filter AST and collects all the evttypes for which @@ -45,25 +48,32 @@ class filter_evttype_resolver: private libsinsp::filter::ast::expr_visitor \param filter The filter AST to be explored \param out The set to be filled with the evttypes */ - void evttypes(libsinsp::filter::ast::expr* filter, std::set& out); + void evttypes( + libsinsp::filter::ast::expr* filter, + std::set& out) const; /*! \brief Overloaded version of evttypes() that supports filters wrapped in shared pointers */ - void evttypes(std::shared_ptr filter, - std::set& out); + void evttypes( + std::shared_ptr filter, + std::set& out) const; private: - void visit(libsinsp::filter::ast::and_expr* e) override; - void visit(libsinsp::filter::ast::or_expr* e) override; - void visit(libsinsp::filter::ast::not_expr* e) override; - void visit(libsinsp::filter::ast::value_expr* e) override; - void visit(libsinsp::filter::ast::list_expr* e) override; - void visit(libsinsp::filter::ast::unary_check_expr* e) override; - void visit(libsinsp::filter::ast::binary_check_expr* e) override; - void inversion(std::set& types); + struct visitor : public libsinsp::filter::ast::expr_visitor + { + bool m_expect_value; + std::set m_last_node_evttypes; - bool m_expect_value; - std::set m_last_node_evttypes; + void visit(libsinsp::filter::ast::and_expr* e) override; + void visit(libsinsp::filter::ast::or_expr* e) override; + void visit(libsinsp::filter::ast::not_expr* e) override; + void visit(libsinsp::filter::ast::value_expr* e) override; + void visit(libsinsp::filter::ast::list_expr* e) override; + void visit(libsinsp::filter::ast::unary_check_expr* e) override; + void visit(libsinsp::filter::ast::binary_check_expr* e) override; + void inversion(std::set& types); + void evttypes(std::string evtname, std::set& out); + }; }; diff --git a/userspace/engine/filter_macro_resolver.cpp b/userspace/engine/filter_macro_resolver.cpp index 3374bbc16b4..7e98499a2b7 100644 --- a/userspace/engine/filter_macro_resolver.cpp +++ b/userspace/engine/filter_macro_resolver.cpp @@ -21,29 +21,37 @@ using namespace libsinsp::filter; bool filter_macro_resolver::run(libsinsp::filter::ast::expr*& filter) { + visitor v; m_unknown_macros.clear(); m_resolved_macros.clear(); - m_last_node_changed = false; - m_last_node = filter; - filter->accept(this); - if (m_last_node_changed) + v.m_unknown_macros = &m_unknown_macros; + v.m_resolved_macros = &m_resolved_macros; + v.m_macros = &m_macros; + v.m_last_node_changed = false; + v.m_last_node = filter; + filter->accept(&v); + if (v.m_last_node_changed) { delete filter; - filter = m_last_node; + filter = v.m_last_node; } return !m_resolved_macros.empty(); } bool filter_macro_resolver::run(std::shared_ptr& filter) { + visitor v; m_unknown_macros.clear(); m_resolved_macros.clear(); - m_last_node_changed = false; - m_last_node = filter.get(); - filter->accept(this); - if (m_last_node_changed) + v.m_unknown_macros = &m_unknown_macros; + v.m_resolved_macros = &m_resolved_macros; + v.m_macros = &m_macros; + v.m_last_node_changed = false; + v.m_last_node = filter.get(); + filter->accept(&v); + if (v.m_last_node_changed) { - filter.reset(m_last_node); + filter.reset(v.m_last_node); } return !m_resolved_macros.empty(); } @@ -55,17 +63,17 @@ void filter_macro_resolver::set_macro( m_macros[name] = macro; } -set& filter_macro_resolver::get_unknown_macros() +const set& filter_macro_resolver::get_unknown_macros() const { return m_unknown_macros; } -set& filter_macro_resolver::get_resolved_macros() +const set& filter_macro_resolver::get_resolved_macros() const { return m_resolved_macros; } -void filter_macro_resolver::visit(ast::and_expr* e) +void filter_macro_resolver::visitor::visit(ast::and_expr* e) { for (size_t i = 0; i < e->children.size(); i++) { @@ -80,7 +88,7 @@ void filter_macro_resolver::visit(ast::and_expr* e) m_last_node_changed = false; } -void filter_macro_resolver::visit(ast::or_expr* e) +void filter_macro_resolver::visitor::visit(ast::or_expr* e) { for (size_t i = 0; i < e->children.size(); i++) { @@ -95,7 +103,7 @@ void filter_macro_resolver::visit(ast::or_expr* e) m_last_node_changed = false; } -void filter_macro_resolver::visit(ast::not_expr* e) +void filter_macro_resolver::visitor::visit(ast::not_expr* e) { e->child->accept(this); if (m_last_node_changed) @@ -107,13 +115,13 @@ void filter_macro_resolver::visit(ast::not_expr* e) m_last_node_changed = false; } -void filter_macro_resolver::visit(ast::list_expr* e) +void filter_macro_resolver::visitor::visit(ast::list_expr* e) { m_last_node = e; m_last_node_changed = false; } -void filter_macro_resolver::visit(ast::binary_check_expr* e) +void filter_macro_resolver::visitor::visit(ast::binary_check_expr* e) { // avoid exploring checks, so that we can be sure that each // value_expr* node visited is a macro identifier @@ -121,29 +129,29 @@ void filter_macro_resolver::visit(ast::binary_check_expr* e) m_last_node_changed = false; } -void filter_macro_resolver::visit(ast::unary_check_expr* e) +void filter_macro_resolver::visitor::visit(ast::unary_check_expr* e) { m_last_node = e; m_last_node_changed = false; } -void filter_macro_resolver::visit(ast::value_expr* e) +void filter_macro_resolver::visitor::visit(ast::value_expr* e) { // we are supposed to get here only in case // of identier-only children from either a 'not', // an 'and' or an 'or'. - auto macro = m_macros.find(e->value); - if (macro != m_macros.end() && macro->second) // skip null-ptr macros + auto macro = m_macros->find(e->value); + if (macro != m_macros->end() && macro->second) // skip null-ptr macros { ast::expr* new_node = ast::clone(macro->second.get()); new_node->accept(this); // this sets m_last_node m_last_node_changed = true; - m_resolved_macros.insert(e->value); + m_resolved_macros->insert(e->value); } else { m_last_node = e; m_last_node_changed = false; - m_unknown_macros.insert(e->value); + m_unknown_macros->insert(e->value); } } diff --git a/userspace/engine/filter_macro_resolver.h b/userspace/engine/filter_macro_resolver.h index 41e59de29d4..5076e40dce5 100644 --- a/userspace/engine/filter_macro_resolver.h +++ b/userspace/engine/filter_macro_resolver.h @@ -26,7 +26,7 @@ limitations under the License. \brief Helper class for substituting and resolving macro references in parsed filters. */ -class filter_macro_resolver: private libsinsp::filter::ast::expr_visitor +class filter_macro_resolver { public: /*! @@ -63,7 +63,7 @@ class filter_macro_resolver: private libsinsp::filter::ast::expr_visitor substituted during the last invocation of run(). Should be non-empty if the last invocation of run() returned true. */ - std::set& get_resolved_macros(); + const std::set& get_resolved_macros() const; /*! \brief Returns a set containing the names of all the macros @@ -71,23 +71,32 @@ class filter_macro_resolver: private libsinsp::filter::ast::expr_visitor A macro remains unresolved if it is found inside the processed filter but it was not defined with set_macro(); */ - std::set& get_unknown_macros(); + const std::set& get_unknown_macros() const; private: - void visit(libsinsp::filter::ast::and_expr* e) override; - void visit(libsinsp::filter::ast::or_expr* e) override; - void visit(libsinsp::filter::ast::not_expr* e) override; - void visit(libsinsp::filter::ast::value_expr* e) override; - void visit(libsinsp::filter::ast::list_expr* e) override; - void visit(libsinsp::filter::ast::unary_check_expr* e) override; - void visit(libsinsp::filter::ast::binary_check_expr* e) override; + typedef std::map< + std::string, + std::shared_ptr + > macro_defs; + + struct visitor : public libsinsp::filter::ast::expr_visitor + { + bool m_last_node_changed; + libsinsp::filter::ast::expr* m_last_node; + std::set* m_unknown_macros; + std::set* m_resolved_macros; + macro_defs* m_macros; + + void visit(libsinsp::filter::ast::and_expr* e) override; + void visit(libsinsp::filter::ast::or_expr* e) override; + void visit(libsinsp::filter::ast::not_expr* e) override; + void visit(libsinsp::filter::ast::value_expr* e) override; + void visit(libsinsp::filter::ast::list_expr* e) override; + void visit(libsinsp::filter::ast::unary_check_expr* e) override; + void visit(libsinsp::filter::ast::binary_check_expr* e) override; + }; - bool m_last_node_changed; - libsinsp::filter::ast::expr* m_last_node; std::set m_unknown_macros; std::set m_resolved_macros; - std::map< - std::string, - std::shared_ptr - > m_macros; + macro_defs m_macros; }; diff --git a/userspace/engine/indexed_vector.h b/userspace/engine/indexed_vector.h index e36d50e9fe5..41bacecb77e 100644 --- a/userspace/engine/indexed_vector.h +++ b/userspace/engine/indexed_vector.h @@ -28,10 +28,12 @@ template class indexed_vector { public: + virtual ~indexed_vector() = default; + /*! \brief Returns the number of elements */ - virtual inline size_t size() + virtual inline size_t size() const { return m_entries.size(); } @@ -39,7 +41,7 @@ class indexed_vector /*! \brief Returns true if the vector is empty */ - virtual inline bool empty() + virtual inline bool empty() const { return m_entries.empty(); } diff --git a/userspace/engine/rule_loader.cpp b/userspace/engine/rule_loader.cpp index 6abcaf39e56..df8a9ea7879 100644 --- a/userspace/engine/rule_loader.cpp +++ b/userspace/engine/rule_loader.cpp @@ -61,19 +61,16 @@ static bool is_field_defined( return false; } -// todo(jasondellaluce): add an helper in libsinsp for this -static bool is_operator_defined(const string& op) +static inline bool is_operator_defined(const string& op) { - static vector ops = {"=", "==", "!=", "<=", ">=", "<", ">", - "contains", "icontains", "bcontains", "glob", "bstartswith", - "startswith", "endswith", "in", "intersects", "pmatch"}; + auto ops = libsinsp::filter::parser::supported_operators(); return find(ops.begin(), ops.end(), op) != ops.end(); } -// todo(jasondellaluce): add an helper in libsinsp for this -static bool is_operator_for_list(const string& op) +static inline bool is_operator_for_list(const string& op) { - return op == "in" || op == "intersects" || op == "pmatch"; + auto ops = libsinsp::filter::parser::supported_operators(true); + return find(ops.begin(), ops.end(), op) != ops.end(); } static bool is_format_valid( @@ -706,8 +703,7 @@ void rule_loader::compile_rule_infos( set evttypes; if(rule.source == falco_common::syscall_source) { - filter_evttype_resolver resolver; - resolver.evttypes(ast, evttypes); + filter_evttype_resolver().evttypes(ast, evttypes); if ((evttypes.empty() || evttypes.size() > 100) && r.warn_evttypes) { diff --git a/userspace/engine/rule_loader.h b/userspace/engine/rule_loader.h index 1fa032c8247..c1b7247e219 100644 --- a/userspace/engine/rule_loader.h +++ b/userspace/engine/rule_loader.h @@ -67,7 +67,7 @@ class rule_loader */ struct configuration { - configuration(const std::string& cont): content(cont) {} + explicit configuration(const std::string& cont): content(cont) {} const std::string& content; std::string output_extra; bool replace_output_container_info; @@ -172,6 +172,8 @@ class rule_loader bool skip_if_unknown_filter; }; + virtual ~rule_loader() = default; + /*! \brief Erases all the internal state and definitions */ diff --git a/userspace/engine/rule_reader.h b/userspace/engine/rule_reader.h index 5abd4b35655..b3e94341eae 100644 --- a/userspace/engine/rule_reader.h +++ b/userspace/engine/rule_reader.h @@ -27,6 +27,8 @@ limitations under the License. class rule_reader { public: + virtual ~rule_reader() = default; + /*! \brief Reads the contents of a ruleset and uses a loader to store thew new definitions