refactor(userspace/engine): adapt existing ruleset implementation to new filter_ruleset interface

Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
This commit is contained in:
Jason Dellaluce 2022-04-14 14:02:31 +00:00 committed by poiana
parent bbbdb311e0
commit 3af8d1c0d2
4 changed files with 212 additions and 36 deletions

View File

@ -15,7 +15,7 @@ set(FALCO_ENGINE_SOURCE_FILES
falco_engine.cpp
falco_utils.cpp
json_evt.cpp
ruleset.cpp
evttype_index_ruleset.cpp
formats.cpp
filter_macro_resolver.cpp
filter_evttype_resolver.cpp

View File

@ -14,30 +14,32 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ruleset.h"
#include "evttype_index_ruleset.h"
#include "filter_evttype_resolver.h"
#include "banned.h" // This raises a compilation error when certain functions are used
#include <algorithm>
using namespace std;
falco_ruleset::falco_ruleset()
evttype_index_ruleset::evttype_index_ruleset(
std::shared_ptr<gen_event_filter_factory> f): m_filter_factory(f)
{
}
falco_ruleset::~falco_ruleset()
evttype_index_ruleset::~evttype_index_ruleset()
{
}
falco_ruleset::ruleset_filters::ruleset_filters()
evttype_index_ruleset::ruleset_filters::ruleset_filters()
{
}
falco_ruleset::ruleset_filters::~ruleset_filters()
evttype_index_ruleset::ruleset_filters::~ruleset_filters()
{
}
void falco_ruleset::ruleset_filters::add_wrapper_to_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap)
void evttype_index_ruleset::ruleset_filters::add_wrapper_to_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap)
{
// This is O(n) but it's also uncommon
// (when loading rules only).
@ -51,7 +53,7 @@ void falco_ruleset::ruleset_filters::add_wrapper_to_list(filter_wrapper_list &wr
}
}
void falco_ruleset::ruleset_filters::remove_wrapper_from_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap)
void evttype_index_ruleset::ruleset_filters::remove_wrapper_from_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap)
{
// This is O(n) but it's also uncommon
// (when loading rules only).
@ -64,7 +66,7 @@ void falco_ruleset::ruleset_filters::remove_wrapper_from_list(filter_wrapper_lis
}
}
void falco_ruleset::ruleset_filters::add_filter(std::shared_ptr<filter_wrapper> wrap)
void evttype_index_ruleset::ruleset_filters::add_filter(std::shared_ptr<filter_wrapper> wrap)
{
if(wrap->evttypes.empty())
{
@ -87,7 +89,7 @@ void falco_ruleset::ruleset_filters::add_filter(std::shared_ptr<filter_wrapper>
m_filters.insert(wrap);
}
void falco_ruleset::ruleset_filters::remove_filter(std::shared_ptr<filter_wrapper> wrap)
void evttype_index_ruleset::ruleset_filters::remove_filter(std::shared_ptr<filter_wrapper> wrap)
{
if(wrap->evttypes.empty())
{
@ -107,12 +109,12 @@ void falco_ruleset::ruleset_filters::remove_filter(std::shared_ptr<filter_wrappe
m_filters.erase(wrap);
}
uint64_t falco_ruleset::ruleset_filters::num_filters()
uint64_t evttype_index_ruleset::ruleset_filters::num_filters()
{
return m_filters.size();
}
bool falco_ruleset::ruleset_filters::run(gen_event *evt)
bool evttype_index_ruleset::ruleset_filters::run(gen_event *evt, falco_rule& match)
{
if(evt->get_type() < m_filter_by_event_type.size())
{
@ -120,6 +122,7 @@ bool falco_ruleset::ruleset_filters::run(gen_event *evt)
{
if(wrap->filter->run(evt))
{
match = wrap->rule;
return true;
}
}
@ -130,6 +133,7 @@ bool falco_ruleset::ruleset_filters::run(gen_event *evt)
{
if(wrap->filter->run(evt))
{
match = wrap->rule;
return true;
}
}
@ -137,7 +141,7 @@ bool falco_ruleset::ruleset_filters::run(gen_event *evt)
return false;
}
void falco_ruleset::ruleset_filters::evttypes_for_ruleset(std::set<uint16_t> &evttypes)
void evttype_index_ruleset::ruleset_filters::evttypes_for_ruleset(std::set<uint16_t> &evttypes)
{
evttypes.clear();
@ -147,23 +151,54 @@ void falco_ruleset::ruleset_filters::evttypes_for_ruleset(std::set<uint16_t> &ev
}
}
void falco_ruleset::add(string &source,
string &name,
set<string> &tags,
set<uint16_t> &evttypes,
std::shared_ptr<gen_event_filter> filter)
void evttype_index_ruleset::add(
const falco_rule& rule,
std::shared_ptr<libsinsp::filter::ast::expr> condition)
{
std::shared_ptr<filter_wrapper> wrap(new filter_wrapper());
wrap->source = source;
wrap->name = name;
wrap->tags = tags;
wrap->filter = filter;
wrap->evttypes = evttypes;
m_filters.insert(wrap);
try
{
sinsp_filter_compiler compiler(m_filter_factory, condition.get());
shared_ptr<gen_event_filter> filter(compiler.compile());
std::shared_ptr<filter_wrapper> wrap(new filter_wrapper());
filter_evttype_resolver resolver;
wrap->rule = rule;
wrap->filter = filter;
resolver.evttypes(condition, wrap->evttypes);
m_filters.insert(wrap);
}
catch (const sinsp_exception& e)
{
throw falco_exception(string(e.what()));
}
}
void falco_ruleset::enable(const string &substring, bool match_exact, bool enabled, uint16_t ruleset)
uint16_t evttype_index_ruleset::ruleset_id(const std::string &name)
{
auto it = find(m_ruleset_names.begin(), m_ruleset_names.end(), name);
if (it != m_ruleset_names.end())
{
return it - m_ruleset_names.begin();
}
m_ruleset_names.push_back(name);
return m_ruleset_names.size() - 1;
}
void evttype_index_ruleset::on_loading_complete()
{
// nothing to do for now
}
void evttype_index_ruleset::clear()
{
for (size_t i = 0; i < m_rulesets.size(); i++)
{
std::shared_ptr<ruleset_filters> r(new ruleset_filters());
m_rulesets[i] = r;
}
m_filters.clear();
}
void evttype_index_ruleset::enable(const string &substring, bool match_exact, bool enabled, uint16_t ruleset)
{
while(m_rulesets.size() < (size_t)ruleset + 1)
{
@ -176,14 +211,14 @@ void falco_ruleset::enable(const string &substring, bool match_exact, bool enabl
if(match_exact)
{
size_t pos = wrap->name.find(substring);
size_t pos = wrap->rule.name.find(substring);
matches = (substring == "" || (pos == 0 &&
substring.size() == wrap->name.size()));
substring.size() == wrap->rule.name.size()));
}
else
{
matches = (substring == "" || (wrap->name.find(substring) != string::npos));
matches = (substring == "" || (wrap->rule.name.find(substring) != string::npos));
}
if(matches)
@ -200,7 +235,7 @@ void falco_ruleset::enable(const string &substring, bool match_exact, bool enabl
}
}
void falco_ruleset::enable_tags(const set<string> &tags, bool enabled, uint16_t ruleset)
void evttype_index_ruleset::enable_tags(const set<string> &tags, bool enabled, uint16_t ruleset)
{
while(m_rulesets.size() < (size_t)ruleset + 1)
{
@ -212,7 +247,7 @@ void falco_ruleset::enable_tags(const set<string> &tags, bool enabled, uint16_t
std::set<string> intersect;
set_intersection(tags.begin(), tags.end(),
wrap->tags.begin(), wrap->tags.end(),
wrap->rule.tags.begin(), wrap->rule.tags.end(),
inserter(intersect, intersect.begin()));
if(!intersect.empty())
@ -229,7 +264,7 @@ void falco_ruleset::enable_tags(const set<string> &tags, bool enabled, uint16_t
}
}
uint64_t falco_ruleset::num_rules_for_ruleset(uint16_t ruleset)
uint64_t evttype_index_ruleset::enabled_count(uint16_t ruleset)
{
while(m_rulesets.size() < (size_t)ruleset + 1)
{
@ -239,17 +274,17 @@ uint64_t falco_ruleset::num_rules_for_ruleset(uint16_t ruleset)
return m_rulesets[ruleset]->num_filters();
}
bool falco_ruleset::run(gen_event *evt, uint16_t ruleset)
bool evttype_index_ruleset::run(gen_event *evt, falco_rule& match, uint16_t ruleset)
{
if(m_rulesets.size() < (size_t)ruleset + 1)
{
return false;
}
return m_rulesets[ruleset]->run(evt);
return m_rulesets[ruleset]->run(evt, match);
}
void falco_ruleset::evttypes_for_ruleset(set<uint16_t> &evttypes, uint16_t ruleset)
void evttype_index_ruleset::enabled_evttypes(set<uint16_t> &evttypes, uint16_t ruleset)
{
if(m_rulesets.size() < (size_t)ruleset + 1)
{

View File

@ -0,0 +1,140 @@
/*
Copyright (C) 2019 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <string>
#include <set>
#include <vector>
#include <list>
#include <map>
#include "ruleset.h"
#include "sinsp.h"
#include "filter.h"
#include "event.h"
#include "gen_filter.h"
/*!
\brief A filter_ruleset that indexes enabled rules by event type,
and performs linear search on each event type bucket
*/
class evttype_index_ruleset: public filter_ruleset
{
public:
evttype_index_ruleset(std::shared_ptr<gen_event_filter_factory> factory);
virtual ~evttype_index_ruleset();
void add(
const falco_rule& rule,
std::shared_ptr<libsinsp::filter::ast::expr> condition) override;
void clear() override;
uint16_t ruleset_id(const std::string &name) override;
bool run(gen_event *evt, falco_rule& match, uint16_t ruleset = 0);
uint64_t enabled_count(uint16_t ruleset = 0) override;
void on_loading_complete() override;
void enable(
const std::string &substring,
bool match_exact,
bool enabled,
uint16_t ruleset = 0) override;
void enable_tags(
const std::set<std::string> &tags,
bool enabled,
uint16_t ruleset = 0) override;
// evttypes for a ruleset
void enabled_evttypes(
std::set<uint16_t> &evttypes,
uint16_t ruleset) override;
private:
struct filter_wrapper
{
falco_rule rule;
std::set<uint16_t> evttypes;
std::shared_ptr<gen_event_filter> filter;
};
typedef std::list<std::shared_ptr<filter_wrapper>> filter_wrapper_list;
// A group of filters all having the same ruleset
class ruleset_filters {
public:
ruleset_filters();
virtual ~ruleset_filters();
void add_filter(std::shared_ptr<filter_wrapper> wrap);
void remove_filter(std::shared_ptr<filter_wrapper> wrap);
uint64_t num_filters();
bool run(gen_event *evt, falco_rule& match);
void evttypes_for_ruleset(std::set<uint16_t> &evttypes);
private:
void add_wrapper_to_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap);
void remove_wrapper_from_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap);
// Vector indexes from event type to a set of filters. There can
// be multiple filters for a given event type.
// NOTE: This is used only when the event sub-type is 0.
std::vector<filter_wrapper_list> m_filter_by_event_type;
filter_wrapper_list m_filter_all_event_types;
// All filters added. Used to make num_filters() fast.
std::set<std::shared_ptr<filter_wrapper>> m_filters;
};
// Vector indexes from ruleset id to set of rules.
std::vector<std::shared_ptr<ruleset_filters>> m_rulesets;
// All filters added. The set of enabled filters is held in m_rulesets
std::set<std::shared_ptr<filter_wrapper>> m_filters;
std::shared_ptr<gen_event_filter_factory> m_filter_factory;
std::vector<std::string> m_ruleset_names;
};
class evttype_index_ruleset_factory: public filter_ruleset_factory
{
public:
inline evttype_index_ruleset_factory(
std::shared_ptr<gen_event_filter_factory> factory
): m_filter_factory(factory) { }
inline std::shared_ptr<filter_ruleset> new_ruleset() override
{
std::shared_ptr<filter_ruleset> ret(
new evttype_index_ruleset(m_filter_factory));
return ret;
}
private:
std::shared_ptr<gen_event_filter_factory> m_filter_factory;
};

View File

@ -22,6 +22,7 @@ limitations under the License.
struct falco_rule
{
size_t id;
std::string source;
std::string name;
std::string description;