Skip to content

Commit

Permalink
refactor(userspace/engine): polish evttype resolver and use it in rul…
Browse files Browse the repository at this point in the history
…e loader

Signed-off-by: Jason Dellaluce <[email protected]>
  • Loading branch information
jasondellaluce committed Apr 11, 2022
1 parent 17a3147 commit 4478ebb
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 44 deletions.
3 changes: 2 additions & 1 deletion userspace/engine/falco_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,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);
Expand All @@ -409,7 +410,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)
Expand Down
1 change: 1 addition & 0 deletions userspace/engine/falco_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ class falco_engine
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);

//
Expand Down
72 changes: 34 additions & 38 deletions userspace/engine/filter_evttype_resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Expand All @@ -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(
Expand All @@ -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)
Expand All @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions userspace/engine/filter_evttype_resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class filter_evttype_resolver: private libsinsp::filter::ast::expr_visitor
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;
Expand Down
26 changes: 21 additions & 5 deletions userspace/engine/rule_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); } }
Expand Down Expand Up @@ -1077,19 +1078,34 @@ void rule_loader::expand_rule_infos(
throw falco_exception("Rule " + rule.name + ": error " + err);
}
}
engine->add_filter(filter, rule.name, rule.source, rule.tags);
if (rule.source == falco_common::syscall_source
&& r["warn_evttypes"].as<bool>())

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;
evttypes.clear();
resolver.evttypes(ast, evttypes);
if (r["warn_evttypes"].as<bool>()
&& (evttypes.size() == 0 || evttypes.size() > 100))
{
warnings.push_back(
"Rule " + rule.name + ": warning (no-evttype):\n" +
+ " matches too many evt.type values.\n"
+ " 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 };
}

engine->add_filter(filter, rule.name, rule.source, evttypes, rule.tags);
engine->enable_rule(rule.name, r["enabled"].as<bool>());
}
catch (exception& e)
Expand Down

0 comments on commit 4478ebb

Please sign in to comment.