Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: change falco_engine::process_event to lookup sources by index #1944

Merged
merged 1 commit into from
Apr 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 51 additions & 36 deletions userspace/engine/falco_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ void falco_engine::enable_rule(const string &substring, bool enabled, const stri

for(auto &it : m_rulesets)
{
it.second->enable(substring, match_exact, enabled, ruleset_id);
it.ruleset->enable(substring, match_exact, enabled, ruleset_id);
}
}

Expand All @@ -219,7 +219,7 @@ void falco_engine::enable_rule_exact(const string &rule_name, bool enabled, cons

for(auto &it : m_rulesets)
{
it.second->enable(rule_name, match_exact, enabled, ruleset_id);
it.ruleset->enable(rule_name, match_exact, enabled, ruleset_id);
}
}

Expand All @@ -229,7 +229,7 @@ void falco_engine::enable_rule_by_tag(const set<string> &tags, bool enabled, con

for(auto &it : m_rulesets)
{
it.second->enable_tags(tags, enabled, ruleset_id);
it.ruleset->enable_tags(tags, enabled, ruleset_id);
}
}

Expand Down Expand Up @@ -259,7 +259,7 @@ uint64_t falco_engine::num_rules_for_ruleset(const std::string &ruleset)
uint64_t ret = 0;
for(auto &it : m_rulesets)
{
ret += it.second->num_rules_for_ruleset(ruleset_id);
ret += it.ruleset->num_rules_for_ruleset(ruleset_id);
}

return ret;
Expand All @@ -269,14 +269,14 @@ void falco_engine::evttypes_for_ruleset(std::string &source, std::set<uint16_t>
{
uint16_t ruleset_id = find_ruleset_id(ruleset);

auto it = m_rulesets.find(source);
auto it = find_ruleset(source);
if(it == m_rulesets.end())
{
string err = "Unknown event source " + source;
throw falco_exception(err);
}

it->second->evttypes_for_ruleset(evttypes, ruleset_id);
it->ruleset->evttypes_for_ruleset(evttypes, ruleset_id);

}

Expand All @@ -294,47 +294,51 @@ std::shared_ptr<gen_event_formatter> falco_engine::create_formatter(const std::s
return it->second->create_formatter(output);
}

unique_ptr<falco_engine::rule_result> falco_engine::process_event(std::string &source, gen_event *ev, uint16_t ruleset_id)
unique_ptr<falco_engine::rule_result> falco_engine::process_event(std::size_t source_idx, gen_event *ev, uint16_t ruleset_id)
{
if(should_drop_evt())
{
return unique_ptr<struct rule_result>();
}

auto it = m_rulesets.find(source);
if(it == m_rulesets.end())
{
string err = "Unknown event source " + source;
throw falco_exception(err);
}

if (!it->second->run(ev, ruleset_id))
try
{
return unique_ptr<struct rule_result>();
}
auto &r = m_rulesets.at(source_idx);
if(!r.ruleset->run(ev, ruleset_id))
{
return unique_ptr<struct rule_result>();
}

unique_ptr<struct rule_result> res(new rule_result());
res->source = source;
unique_ptr<struct rule_result> res(new rule_result());
res->source = r.source;

populate_rule_result(res, ev);
populate_rule_result(res, ev);

return res;
return res;
}
catch(std::out_of_range const &exc)
{
std::string err = "Unknown event source index " + std::to_string(source_idx);
throw falco_exception(err);
}
}

unique_ptr<falco_engine::rule_result> falco_engine::process_event(std::string &source, gen_event *ev)
unique_ptr<falco_engine::rule_result> falco_engine::process_event(std::size_t source_idx, gen_event *ev)
{
return process_event(source, ev, m_default_ruleset_id);
return process_event(source_idx, ev, m_default_ruleset_id);
}

void falco_engine::add_source(const std::string &source,
std::shared_ptr<gen_event_filter_factory> filter_factory,
std::shared_ptr<gen_event_formatter_factory> formatter_factory)
std::size_t falco_engine::add_source(const std::string &source,
std::shared_ptr<gen_event_filter_factory> filter_factory,
std::shared_ptr<gen_event_formatter_factory> formatter_factory)
{
m_filter_factories[source] = filter_factory;
m_format_factories[source] = formatter_factory;

std::shared_ptr<falco_ruleset> ruleset(new falco_ruleset());
m_rulesets[source] = ruleset;
auto idx = m_rulesets.size();
m_rulesets.emplace_back(source, new falco_ruleset);
// here we just trust the caller they won't add the same source more than once
return idx;
}

void falco_engine::populate_rule_result(unique_ptr<struct rule_result> &res, gen_event *ev)
Expand Down Expand Up @@ -418,19 +422,19 @@ void falco_engine::add_filter(std::shared_ptr<gen_event_filter> filter,
std::string &source,
std::set<std::string> &tags)
{
auto it = m_rulesets.find(source);
auto it = find_ruleset(source);
if(it == m_rulesets.end())
{
string err = "Unknown event source " + source;
throw falco_exception(err);
}

it->second->add(source, rule, tags, filter);
it->ruleset->add(source, rule, tags, filter);
}

bool falco_engine::is_source_valid(const std::string &source)
{
return (m_rulesets.find(source) != m_rulesets.end());
return (find_ruleset(source) != m_rulesets.end());
}

bool falco_engine::is_plugin_compatible(const std::string &name,
Expand Down Expand Up @@ -465,12 +469,9 @@ bool falco_engine::is_plugin_compatible(const std::string &name,

void falco_engine::clear_filters()
{
m_rulesets.clear();

for(auto &it : m_filter_factories)
for(auto &it : m_rulesets)
{
std::shared_ptr<falco_ruleset> ruleset(new falco_ruleset());
m_rulesets[it.first] = ruleset;
it.ruleset.reset(new falco_ruleset);
}

m_required_plugin_versions.clear();
Expand Down Expand Up @@ -507,3 +508,17 @@ inline bool falco_engine::should_drop_evt()
double coin = (random() * (1.0/RAND_MAX));
return (coin >= (1.0/(m_sampling_multiplier * m_sampling_ratio)));
}

inline std::vector<falco_engine::ruleset_node>::iterator falco_engine::find_ruleset(const std::string &source)
{
return std::find_if(
m_rulesets.begin(), m_rulesets.end(),
[&source](const ruleset_node &r) { return r.source == source; });
}

inline std::vector<falco_engine::ruleset_node>::const_iterator falco_engine::find_ruleset(const std::string &source) const
{
return std::find_if(
m_rulesets.cbegin(), m_rulesets.cend(),
[&source](const ruleset_node &r) { return r.source == source; });
}
24 changes: 18 additions & 6 deletions userspace/engine/falco_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,20 +163,21 @@ class falco_engine : public falco_common
// with a ruleset string.
//
// the returned rule_result is allocated and must be delete()d.
std::unique_ptr<rule_result> process_event(std::string &source, gen_event *ev, uint16_t ruleset_id);
std::unique_ptr<rule_result> process_event(std::size_t source_idx, gen_event *ev, uint16_t ruleset_id);

//
// Wrapper assuming the default ruleset
//
std::unique_ptr<rule_result> process_event(std::string &source, gen_event *ev);
std::unique_ptr<rule_result> process_event(std::size_t source_idx, gen_event *ev);

//
// Configure the engine to support events with the provided
// source, with the provided filter factory and formatter factory.
// Return source index for fast lookup.
//
void add_source(const std::string &source,
std::shared_ptr<gen_event_filter_factory> filter_factory,
std::shared_ptr<gen_event_formatter_factory> formatter_factory);
std::size_t add_source(const std::string &source,
std::shared_ptr<gen_event_filter_factory> filter_factory,
std::shared_ptr<gen_event_formatter_factory> formatter_factory);

// Return whether or not there is a valid filter/formatter
// factory for this source.
Expand Down Expand Up @@ -213,6 +214,14 @@ class falco_engine : public falco_common
bool is_plugin_compatible(const std::string &name, const std::string &version, std::string &required_version);

private:
struct ruleset_node
{
ruleset_node(const std::string &n, falco_ruleset *p):
source(n), ruleset(p) {}

std::string source;
mutable std::shared_ptr<falco_ruleset> ruleset;
};

//
// Determine whether the given event should be matched at all
Expand All @@ -221,14 +230,17 @@ class falco_engine : public falco_common
//
inline bool should_drop_evt();

inline std::vector<ruleset_node>::iterator find_ruleset(const std::string &source);
inline std::vector<ruleset_node>::const_iterator find_ruleset(const std::string &source) const;

// Maps from event source to object that can generate filters from rules
std::map<std::string, std::shared_ptr<gen_event_filter_factory>> m_filter_factories;

// Maps from event source to object that can format output strings in rules
std::map<std::string, std::shared_ptr<gen_event_formatter_factory>> m_format_factories;

// Maps from event source to the set of rules for that event source
std::map<std::string, std::shared_ptr<falco_ruleset>> m_rulesets;
std::vector<ruleset_node> m_rulesets;

std::unique_ptr<falco_rules> m_rules;
uint16_t m_next_ruleset_id;
Expand Down
39 changes: 21 additions & 18 deletions userspace/falco/falco.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ bool g_restart = false;
bool g_daemonized = false;

static std::string syscall_source = "syscall";
static std::size_t syscall_source_idx;
static std::string k8s_audit_source = "k8s_audit";
static std::size_t k8s_audit_source_idx;

//
// Helper functions
Expand Down Expand Up @@ -118,7 +120,7 @@ void read_k8s_audit_trace_file(falco_engine *engine,
continue;
}

if(!k8s_audit_handler::accept_data(engine, outputs, line, errstr))
if(!k8s_audit_handler::accept_data(engine, outputs, k8s_audit_source_idx, line, errstr))
{
falco_logger::log(LOG_ERR, "Could not read k8s audit event line #" + to_string(line_num) + ", \"" + line + "\": " + errstr + ", stopping");
return;
Expand All @@ -140,16 +142,16 @@ static std::string read_file(std::string filename)
// Event processing loop
//
uint64_t do_inspect(falco_engine *engine,
falco_outputs *outputs,
sinsp* inspector,
std::string &event_source,
falco_configuration &config,
syscall_evt_drop_mgr &sdropmgr,
uint64_t duration_to_tot_ns,
string &stats_filename,
uint64_t stats_interval,
bool all_events,
int &result)
falco_outputs *outputs,
sinsp *inspector,
std::size_t event_source_idx,
falco_configuration &config,
syscall_evt_drop_mgr &sdropmgr,
uint64_t duration_to_tot_ns,
string &stats_filename,
uint64_t stats_interval,
bool all_events,
int &result)
{
uint64_t num_evts = 0;
int32_t rc;
Expand Down Expand Up @@ -207,7 +209,7 @@ uint64_t do_inspect(falco_engine *engine,
if(unlikely(ev == nullptr))
{
timeouts_since_last_success_or_msg++;
if(event_source == syscall_source &&
if(event_source_idx == syscall_source_idx &&
(timeouts_since_last_success_or_msg > config.m_syscall_evt_timeout_max_consecutives))
{
std::string rule = "Falco internal: timeouts notification";
Expand Down Expand Up @@ -272,7 +274,7 @@ uint64_t do_inspect(falco_engine *engine,
// engine, which will match the event against the set
// of rules. If a match is found, pass the event to
// the outputs.
unique_ptr<falco_engine::rule_result> res = engine->process_event(event_source, ev);
unique_ptr<falco_engine::rule_result> res = engine->process_event(event_source_idx, ev);
if(res)
{
outputs->handle_event(res->evt, res->rule, res->source, res->priority_num, res->format, res->tags);
Expand Down Expand Up @@ -517,8 +519,8 @@ int falco_init(int argc, char **argv)
std::shared_ptr<gen_event_formatter_factory> syscall_formatter_factory(new sinsp_evt_formatter_factory(inspector));
std::shared_ptr<gen_event_formatter_factory> k8s_audit_formatter_factory(new json_event_formatter_factory(k8s_audit_filter_factory));

engine->add_source(syscall_source, syscall_filter_factory, syscall_formatter_factory);
engine->add_source(k8s_audit_source, k8s_audit_filter_factory, k8s_audit_formatter_factory);
syscall_source_idx = engine->add_source(syscall_source, syscall_filter_factory, syscall_formatter_factory);
k8s_audit_source_idx = engine->add_source(k8s_audit_source, k8s_audit_filter_factory, k8s_audit_formatter_factory);

for(const auto &src : app.options().disable_sources)
{
Expand Down Expand Up @@ -581,6 +583,7 @@ int falco_init(int argc, char **argv)
// plugin was found, the source is the source of that
// plugin.
std::string event_source = syscall_source;
std::size_t event_source_idx = syscall_source_idx;

// All filterchecks created by plugins go in this
// list. If we ever support multiple event sources at
Expand Down Expand Up @@ -628,7 +631,7 @@ int falco_init(int argc, char **argv)
inspector->set_input_plugin_open_params(p.m_open_params.c_str());
}

engine->add_source(event_source, plugin_filter_factory, plugin_formatter_factory);
event_source_idx = engine->add_source(event_source, plugin_filter_factory, plugin_formatter_factory);

} else {
extractor_plugins.push_back(plugin);
Expand Down Expand Up @@ -1151,7 +1154,7 @@ int falco_init(int argc, char **argv)
{
std::string ssl_option = (config.m_webserver_ssl_enabled ? " (SSL)" : "");
falco_logger::log(LOG_INFO, "Starting internal webserver, listening on port " + to_string(config.m_webserver_listen_port) + ssl_option + "\n");
webserver.init(&config, engine, outputs);
webserver.init(&config, engine, outputs, k8s_audit_source_idx);
webserver.start();
}

Expand Down Expand Up @@ -1190,7 +1193,7 @@ int falco_init(int argc, char **argv)
num_evts = do_inspect(engine,
outputs,
inspector,
event_source,
event_source_idx,
config,
sdropmgr,
uint64_t(app.options().duration_to_tot*ONE_SECOND_IN_NS),
Expand Down
Loading