Skip to content

Commit

Permalink
update(userspace/engine): allow the engine to match and handle multip…
Browse files Browse the repository at this point in the history
…le rules while processing events

Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
  • Loading branch information
loresuso committed Aug 2, 2023
1 parent 216bed4 commit dc5ebd6
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 27 deletions.
49 changes: 49 additions & 0 deletions userspace/engine/evttype_index_ruleset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,45 @@ bool evttype_index_ruleset::ruleset_filters::run(gen_event *evt, falco_rule& mat
return false;
}

bool evttype_index_ruleset::ruleset_filters::run(gen_event *evt, std::vector<falco_rule>& matches)
{
bool match_found = false;

if(evt->get_type() < m_filter_by_event_type.size())
{
for(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(auto &wrap : m_filter_all_event_types)
{
if(wrap->filter->run(evt))
{
matches.push_back(wrap->rule);
match_found = true;
}
}

if(match_found)
{
return true;
}

return false;
}

libsinsp::events::set<ppm_sc_code> evttype_index_ruleset::ruleset_filters::sc_codes()
{
libsinsp::events::set<ppm_sc_code> res;
Expand Down Expand Up @@ -308,6 +347,16 @@ bool evttype_index_ruleset::run(gen_event *evt, falco_rule& match, uint16_t rule
return m_rulesets[ruleset_id]->run(evt, match);
}

bool evttype_index_ruleset::run(gen_event *evt, std::vector<falco_rule>& matches, uint16_t ruleset_id)
{
if(m_rulesets.size() < (size_t)ruleset_id + 1)
{
return false;
}

return m_rulesets[ruleset_id]->run(evt, matches);
}

void evttype_index_ruleset::enabled_evttypes(std::set<uint16_t> &evttypes, uint16_t ruleset_id)
{
evttypes.clear();
Expand Down
9 changes: 8 additions & 1 deletion userspace/engine/evttype_index_ruleset.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class evttype_index_ruleset: public filter_ruleset

void clear() override;

bool run(gen_event *evt, falco_rule& match, uint16_t rulset_id);
bool run(gen_event *evt, falco_rule& match, uint16_t ruleset_id) override;
bool run(gen_event *evt, std::vector<falco_rule>&matches, uint16_t ruleset_id) override;

uint64_t enabled_count(uint16_t ruleset_id) override;

Expand Down Expand Up @@ -118,8 +119,14 @@ class evttype_index_ruleset: public filter_ruleset

uint64_t num_filters();

// Evaluate an event against the ruleset and return the first rule
// that matched.
bool run(gen_event *evt, falco_rule& match);

// Evaluate an event against the ruleset and return all the
// matching rules.
bool run(gen_event *evt, std::vector<falco_rule>& matches);

libsinsp::events::set<ppm_sc_code> sc_codes();

libsinsp::events::set<ppm_event_code> event_codes();
Expand Down
59 changes: 46 additions & 13 deletions userspace/engine/falco_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ falco_engine::falco_engine(bool seed_rng)
m_syscall_source_idx(SIZE_MAX),
m_next_ruleset_id(0),
m_min_priority(falco_common::PRIORITY_DEBUG),
m_rule_matching(falco_common::FIRST),
m_sampling_ratio(1), m_sampling_multiplier(0),
m_replace_container_info(false)
{
Expand Down Expand Up @@ -311,6 +312,11 @@ void falco_engine::set_min_priority(falco_common::priority_type priority)
m_min_priority = priority;
}

void falco_engine::set_rule_matching(falco_common::rule_matching rule_matching)
{
m_rule_matching = rule_matching;
}

uint16_t falco_engine::find_ruleset_id(const std::string &ruleset)
{
auto it = m_known_rulesets.lower_bound(ruleset);
Expand Down Expand Up @@ -354,7 +360,7 @@ std::shared_ptr<gen_event_formatter> falco_engine::create_formatter(const std::s
return find_source(source)->formatter_factory->create_formatter(output);
}

std::unique_ptr<falco_engine::rule_result> falco_engine::process_event(std::size_t source_idx, gen_event *ev, uint16_t ruleset_id)
std::unique_ptr<std::vector<falco_engine::rule_result>> falco_engine::process_event(std::size_t source_idx, gen_event *ev, uint16_t ruleset_id)
{
// note: there are no thread-safety guarantees on the filter_ruleset::run()
// method, but the thread-safety assumptions of falco_engine::process_event()
Expand All @@ -378,24 +384,51 @@ std::unique_ptr<falco_engine::rule_result> falco_engine::process_event(std::size
source = find_source(source_idx);
}

if(should_drop_evt() || !source || !source->ruleset->run(ev, source->m_rule, ruleset_id))
if(should_drop_evt() || !source)
{
return std::unique_ptr<struct rule_result>();
return nullptr;
}

std::unique_ptr<struct rule_result> res(new rule_result());
res->evt = ev;
res->rule = source->m_rule.name;
res->source = source->m_rule.source;
res->format = source->m_rule.output;
res->priority_num = source->m_rule.priority;
res->tags = source->m_rule.tags;
res->exception_fields = source->m_rule.exception_fields;
m_rule_stats_manager.on_event(source->m_rule);
if (m_rule_matching == falco_common::rule_matching::ALL)
{
if (!source->ruleset->run(ev, source->m_rules, ruleset_id))
{
return nullptr;
}
}
else if (m_rule_matching == falco_common::rule_matching::FIRST)
{
falco_rule rule;
if (!source->ruleset->run(ev, rule, ruleset_id))
{
return nullptr;
}
source->m_rules.push_back(rule);
}

auto res = std::make_unique<std::vector<falco_engine::rule_result>>();
for(auto rule : source->m_rules)
{
rule_result rule_result;
rule_result.evt = ev;
rule_result.rule = rule.name;
rule_result.source = rule.source;
rule_result.format = rule.output;
rule_result.priority_num = rule.priority;
rule_result.tags = rule.tags;
rule_result.exception_fields = rule.exception_fields;
m_rule_stats_manager.on_event(rule);
res->push_back(rule_result);
}

if (source->m_rules.size() > 0)
{
source->m_rules.clear();
}
return res;
}

std::unique_ptr<falco_engine::rule_result> falco_engine::process_event(std::size_t source_idx, gen_event *ev)
std::unique_ptr<std::vector<falco_engine::rule_result>> falco_engine::process_event(std::size_t source_idx, gen_event *ev)
{
return process_event(source_idx, ev, m_default_ruleset_id);
}
Expand Down
10 changes: 8 additions & 2 deletions userspace/engine/falco_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ class falco_engine
// Only load rules having this priority or more severe.
void set_min_priority(falco_common::priority_type priority);

// Whether or not continuing to evaluate rules for other potential matches
// even if a match already occurred. This option can be set to avoid shadowing
// of rules.
void set_rule_matching(falco_common::rule_matching rule_matching);

//
// Return the ruleset id corresponding to this ruleset name,
// creating a new one if necessary. If you provide any ruleset
Expand Down Expand Up @@ -189,14 +194,14 @@ class falco_engine
// event source is not thread-safe of its own, so invoking this method
// concurrently with the same source_idx would inherently cause data races
// and lead to undefined behavior.
std::unique_ptr<rule_result> process_event(std::size_t source_idx, gen_event *ev, uint16_t ruleset_id);
std::unique_ptr<std::vector<rule_result>> process_event(std::size_t source_idx, gen_event *ev, uint16_t ruleset_id);

//
// Wrapper assuming the default ruleset.
//
// This inherits the same thread-safety guarantees.
//
std::unique_ptr<rule_result> process_event(std::size_t source_idx, gen_event *ev);
std::unique_ptr<std::vector<rule_result>> process_event(std::size_t source_idx, gen_event *ev);

//
// Configure the engine to support events with the provided
Expand Down Expand Up @@ -320,6 +325,7 @@ class falco_engine
uint16_t m_next_ruleset_id;
std::map<std::string, uint16_t> m_known_rulesets;
falco_common::priority_type m_min_priority;
falco_common::rule_matching m_rule_matching;

//
// Here's how the sampling ratio and multiplier influence
Expand Down
2 changes: 1 addition & 1 deletion userspace/engine/falco_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct falco_source

// Used by the filter_ruleset interface. Filled in when a rule
// matches an event.
mutable falco_rule m_rule;
mutable std::vector<falco_rule> m_rules;

inline bool is_field_defined(const std::string& field) const
{
Expand Down
15 changes: 14 additions & 1 deletion userspace/engine/filter_ruleset.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,27 @@ class filter_ruleset
\brief Processes an event and tries to find a match in a given ruleset.
\return true if a match is found, false otherwise
\param evt The event to be processed
\param match If true is returned, this is filled-out with the rule
\param match If true is returned, this is filled-out with the first rule
that matched the event
\param ruleset_id The id of the ruleset to be used
*/
virtual bool run(
gen_event *evt,
falco_rule& match,
uint16_t ruleset_id) = 0;

/*!
\brief Processes an event and tries to find a match in a given ruleset.
\return true if a match is found, false otherwise
\param evt The event to be processed
\param matches If true is returned, this is filled-out with all the rules
that matched the event
\param ruleset_id The id of the ruleset to be used
*/
virtual bool run(
gen_event *evt,
std::vector<falco_rule>& matches,
uint16_t ruleset_id) = 0;

/*!
\brief Returns the number of rules enabled in a given ruleset
Expand Down
21 changes: 12 additions & 9 deletions userspace/falco/app/actions/process_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,19 +330,22 @@ static falco::app::run_result do_inspect(
// engine, which will match the event against the set
// of rules. If a match is found, pass the event to
// the outputs.
std::unique_ptr<falco_engine::rule_result> res = s.engine->process_event(source_engine_idx, ev);
if(res)
auto res = s.engine->process_event(source_engine_idx, ev);
if(res != nullptr)
{
if (!rate_limiter_enabled || rate_limiter.claim())
for(auto& rule_res : *res.get())
{
s.outputs->handle_event(res->evt, res->rule, res->source, res->priority_num, res->format, res->tags);
}
else
{
falco_logger::log(LOG_DEBUG, "Skipping rate-limited notification for rule " + res->rule + "\n");
if (!rate_limiter_enabled || rate_limiter.claim())
{
s.outputs->handle_event(rule_res.evt, rule_res.rule, rule_res.source, rule_res.priority_num, rule_res.format, rule_res.tags);
}
else
{
falco_logger::log(LOG_DEBUG, "Skipping rate-limited notification for rule " + rule_res.rule + "\n");
}
}
}

num_evts++;
}

Expand Down

0 comments on commit dc5ebd6

Please sign in to comment.