mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-05 08:40:52 +00:00
refactor(userspace/engine): polish evttype resolver and use it in rule loader
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
This commit is contained in:
@@ -412,6 +412,7 @@ void falco_engine::print_stats()
|
||||
void falco_engine::add_filter(std::shared_ptr<gen_event_filter> filter,
|
||||
std::string &rule,
|
||||
std::string &source,
|
||||
std::set<uint16_t> &evttypes,
|
||||
std::set<std::string> &tags)
|
||||
{
|
||||
auto it = find_ruleset(source);
|
||||
@@ -421,7 +422,7 @@ void falco_engine::add_filter(std::shared_ptr<gen_event_filter> filter,
|
||||
throw falco_exception(err);
|
||||
}
|
||||
|
||||
it->ruleset->add(source, rule, tags, filter);
|
||||
it->ruleset->add(source, rule, tags, evttypes, filter);
|
||||
}
|
||||
|
||||
bool falco_engine::is_source_valid(const std::string &source)
|
||||
|
@@ -203,6 +203,7 @@ public:
|
||||
void add_filter(std::shared_ptr<gen_event_filter> filter,
|
||||
std::string &rule,
|
||||
std::string &source,
|
||||
std::set<uint16_t> &evttypes,
|
||||
std::set<std::string> &tags);
|
||||
|
||||
//
|
||||
|
@@ -27,15 +27,29 @@ static bool is_evttype_operator(const string& op)
|
||||
return op == "==" || op == "=" || op == "!=" || op == "in";
|
||||
}
|
||||
|
||||
void filter_evttype_resolver::inversion(set<uint16_t>& types)
|
||||
{
|
||||
set<uint16_t> all_types;
|
||||
evttypes("", all_types);
|
||||
if (types != all_types) // we don't invert the "all types" set
|
||||
{
|
||||
set<uint16_t> diff = types;
|
||||
types.clear();
|
||||
set_difference(
|
||||
all_types.begin(), all_types.end(), diff.begin(), diff.end(),
|
||||
inserter(types, types.begin()));
|
||||
}
|
||||
}
|
||||
|
||||
void filter_evttype_resolver::evttypes(string evtname, set<uint16_t>& out)
|
||||
{
|
||||
// Fill in from 2 to PPM_EVENT_MAX-1. 0 and 1 are excluded as
|
||||
// those are PPM_GENERIC_E/PPME_GENERIC_X.
|
||||
// those are PPM_GENERIC_E/PPME_GENERIC_X
|
||||
const struct ppm_event_info* etable = g_infotables.m_event_info;
|
||||
for(uint16_t i = 2; i < PPM_EVENT_MAX; i++)
|
||||
{
|
||||
// Skip "old" event versions that have been replaced
|
||||
// by newer event versions, or events that are unused.
|
||||
// Skip "old" event versions, unused events, or events not matching
|
||||
// the requested evtname
|
||||
if(!(etable[i].flags & (EF_OLD_VERSION | EF_UNUSED))
|
||||
&& (evtname.empty() || string(etable[i].name) == evtname))
|
||||
{
|
||||
@@ -49,9 +63,7 @@ void filter_evttype_resolver::evttypes(ast::expr* filter, set<uint16_t>& out)
|
||||
m_expect_value = false;
|
||||
m_last_node_evttypes.clear();
|
||||
filter->accept(this);
|
||||
copy(m_last_node_evttypes.begin(),
|
||||
m_last_node_evttypes.end(),
|
||||
inserter(out, out.begin()));
|
||||
out.insert(m_last_node_evttypes.begin(), m_last_node_evttypes.end());
|
||||
}
|
||||
|
||||
void filter_evttype_resolver::evttypes(
|
||||
@@ -60,57 +72,47 @@ void filter_evttype_resolver::evttypes(
|
||||
m_expect_value = false;
|
||||
m_last_node_evttypes.clear();
|
||||
filter.get()->accept(this);
|
||||
copy(m_last_node_evttypes.begin(),
|
||||
m_last_node_evttypes.end(),
|
||||
inserter(out, out.begin()));
|
||||
out.insert(m_last_node_evttypes.begin(), 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)
|
||||
{
|
||||
set<uint16_t> nodetypes;
|
||||
evttypes("", nodetypes);
|
||||
set<uint16_t> types, inters;
|
||||
evttypes("", types);
|
||||
m_last_node_evttypes.clear();
|
||||
for (auto &c : e->children)
|
||||
{
|
||||
set<uint16_t> inters;
|
||||
inters.clear();
|
||||
c->accept(this);
|
||||
set_intersection(
|
||||
nodetypes.begin(), nodetypes.end(),
|
||||
types.begin(), types.end(),
|
||||
m_last_node_evttypes.begin(), m_last_node_evttypes.end(),
|
||||
std::inserter(inters, inters.begin()));
|
||||
nodetypes = inters;
|
||||
inserter(inters, inters.begin()));
|
||||
types = inters;
|
||||
}
|
||||
m_last_node_evttypes = nodetypes;
|
||||
m_last_node_evttypes = types;
|
||||
}
|
||||
|
||||
// "or" nodes evttypes are the union of the evttypes their children
|
||||
void filter_evttype_resolver::visit(ast::or_expr* e)
|
||||
{
|
||||
set<uint16_t> nodetypes;
|
||||
set<uint16_t> types;
|
||||
m_last_node_evttypes.clear();
|
||||
for (auto &c : e->children)
|
||||
{
|
||||
c->accept(this);
|
||||
copy(m_last_node_evttypes.begin(),
|
||||
m_last_node_evttypes.end(),
|
||||
inserter(nodetypes, nodetypes.begin()));
|
||||
types.insert(m_last_node_evttypes.begin(), m_last_node_evttypes.end());
|
||||
}
|
||||
m_last_node_evttypes = nodetypes;
|
||||
m_last_node_evttypes = types;
|
||||
}
|
||||
|
||||
void filter_evttype_resolver::visit(ast::not_expr* e)
|
||||
{
|
||||
set<uint16_t> diff, all_types;
|
||||
m_last_node_evttypes.clear();
|
||||
e->child->accept(this);
|
||||
evttypes("", all_types);
|
||||
if (all_types != m_last_node_evttypes)
|
||||
{
|
||||
diff = m_last_node_evttypes;
|
||||
m_last_node_evttypes.clear();
|
||||
set_difference(
|
||||
all_types.begin(), all_types.end(), diff.begin(), diff.end(),
|
||||
inserter(m_last_node_evttypes, m_last_node_evttypes.begin()));
|
||||
}
|
||||
inversion(m_last_node_evttypes);
|
||||
}
|
||||
|
||||
void filter_evttype_resolver::visit(ast::binary_check_expr* e)
|
||||
@@ -123,13 +125,7 @@ void filter_evttype_resolver::visit(ast::binary_check_expr* e)
|
||||
m_expect_value = false;
|
||||
if (e->op == "!=")
|
||||
{
|
||||
set<uint16_t> all_types;
|
||||
set<uint16_t> diff = m_last_node_evttypes;
|
||||
m_last_node_evttypes.clear();
|
||||
evttypes("", all_types);
|
||||
set_difference(
|
||||
all_types.begin(), all_types.end(), diff.begin(), diff.end(),
|
||||
inserter(m_last_node_evttypes, m_last_node_evttypes.begin()));
|
||||
inversion(m_last_node_evttypes);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@@ -62,6 +62,7 @@ private:
|
||||
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<uint16_t>& types);
|
||||
|
||||
bool m_expect_value;
|
||||
std::set<uint16_t> m_last_node_evttypes;
|
||||
|
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
#include "falco_engine.h"
|
||||
#include "rule_loader.h"
|
||||
#include "filter_macro_resolver.h"
|
||||
#include "filter_evttype_resolver.h"
|
||||
|
||||
#define MAX_VISIBILITY ((uint32_t) -1)
|
||||
#define THROW(cond, err) { if (cond) { throw falco_exception(err); } }
|
||||
@@ -701,11 +702,14 @@ void rule_loader::compile_rule_infos(
|
||||
throw falco_exception("Rule " + rule.name + ": error " + err);
|
||||
}
|
||||
}
|
||||
cfg.engine->add_filter(filter, rule.name, rule.source, rule.tags);
|
||||
if (rule.source == falco_common::syscall_source && r.warn_evttypes)
|
||||
|
||||
set<uint16_t> evttypes;
|
||||
if(rule.source == falco_common::syscall_source)
|
||||
{
|
||||
auto evttypes = filter->evttypes();
|
||||
if (evttypes.size() == 0 || evttypes.size() > 100)
|
||||
filter_evttype_resolver resolver;
|
||||
resolver.evttypes(ast, evttypes);
|
||||
if ((evttypes.empty() || evttypes.size() > 100)
|
||||
&& r.warn_evttypes)
|
||||
{
|
||||
cfg.warnings.push_back(
|
||||
"Rule " + rule.name + ": warning (no-evttype):\n" +
|
||||
@@ -713,6 +717,18 @@ void rule_loader::compile_rule_infos(
|
||||
+ " This has a significant performance penalty.");
|
||||
}
|
||||
}
|
||||
else if (rule.source == "k8s_audit")
|
||||
{
|
||||
// todo(jasondellaluce): remove this case once k8saudit
|
||||
// gets ported to a plugin
|
||||
evttypes = { ppm_event_type::PPME_GENERIC_X };
|
||||
}
|
||||
else
|
||||
{
|
||||
evttypes = { ppm_event_type::PPME_PLUGINEVENT_E };
|
||||
}
|
||||
|
||||
cfg.engine->add_filter(filter, rule.name, rule.source, evttypes, rule.tags);
|
||||
cfg.engine->enable_rule(rule.name, r.enabled);
|
||||
}
|
||||
catch (exception& e)
|
||||
|
Reference in New Issue
Block a user