diff --git a/userspace/libsinsp/filter.cpp b/userspace/libsinsp/filter.cpp
index 83ea11bc74..420463431d 100644
--- a/userspace/libsinsp/filter.cpp
+++ b/userspace/libsinsp/filter.cpp
@@ -31,6 +31,7 @@ along with sysdig. If not, see .
#endif
#include
+#include
#include "sinsp.h"
#include "sinsp_int.h"
@@ -2067,13 +2068,31 @@ sinsp_filter* sinsp_filter_compiler::compile_()
}
sinsp_evttype_filter::sinsp_evttype_filter()
- : m_cur_order(0)
{
- memset(m_filter_by_evttype, 0, PPM_EVENT_MAX * sizeof(list *));
- memset(m_filter_by_syscall, 0, PPM_SC_MAX * sizeof(list *));
}
sinsp_evttype_filter::~sinsp_evttype_filter()
+{
+ for(const auto &val : m_filters)
+ {
+ delete val.second->filter;
+ delete val.second;
+ }
+
+ for(auto &ruleset : m_rulesets)
+ {
+ delete ruleset;
+ }
+ m_filters.clear();
+}
+
+sinsp_evttype_filter::ruleset_filters::ruleset_filters()
+{
+ memset(m_filter_by_evttype, 0, PPM_EVENT_MAX * sizeof(list *));
+ memset(m_filter_by_syscall, 0, PPM_SC_MAX * sizeof(list *));
+}
+
+sinsp_evttype_filter::ruleset_filters::~ruleset_filters()
{
for(int i = 0; i < PPM_EVENT_MAX; i++)
{
@@ -2092,26 +2111,144 @@ sinsp_evttype_filter::~sinsp_evttype_filter()
m_filter_by_syscall[i] = NULL;
}
}
+}
- m_catchall_filters.clear();
+void sinsp_evttype_filter::ruleset_filters::add_filter(filter_wrapper *wrap)
+{
+ for(uint32_t etype = 0; etype < PPM_EVENT_MAX; etype++)
+ {
+ if(wrap->evttypes[etype])
+ {
+ if(!m_filter_by_evttype[etype])
+ {
+ m_filter_by_evttype[etype] = new std::list();
+ }
- for(const auto &val : m_filters)
+ m_filter_by_evttype[etype]->push_back(wrap);
+ }
+ }
+
+ for(uint32_t syscall = 0; syscall < PPM_SC_MAX; syscall++)
{
- delete val.second->filter;
- delete val.second;
+ if(wrap->syscalls[syscall])
+ {
+ if(!m_filter_by_syscall[syscall])
+ {
+ m_filter_by_syscall[syscall] = new std::list();
+ }
+
+ m_filter_by_syscall[syscall]->push_back(wrap);
+ }
}
- m_filters.clear();
}
-sinsp_evttype_filter::filter_wrapper::filter_wrapper()
- : enabled{true}
+void sinsp_evttype_filter::ruleset_filters::remove_filter(filter_wrapper *wrap)
{
+ for(uint32_t etype = 0; etype < PPM_EVENT_MAX; etype++)
+ {
+ if(wrap->evttypes[etype])
+ {
+ if(m_filter_by_evttype[etype])
+ {
+ m_filter_by_evttype[etype]->erase(std::remove(m_filter_by_evttype[etype]->begin(),
+ m_filter_by_evttype[etype]->end(),
+ wrap),
+ m_filter_by_evttype[etype]->end());
+
+ if(m_filter_by_evttype[etype]->size() == 0)
+ {
+ delete m_filter_by_evttype[etype];
+ m_filter_by_evttype[etype] = NULL;
+ }
+ }
+ }
+ }
+
+ for(uint32_t syscall = 0; syscall < PPM_SC_MAX; syscall++)
+ {
+ if(wrap->syscalls[syscall])
+ {
+ if(m_filter_by_syscall[syscall])
+ {
+ m_filter_by_syscall[syscall]->erase(std::remove(m_filter_by_syscall[syscall]->begin(),
+ m_filter_by_syscall[syscall]->end(),
+ wrap),
+ m_filter_by_syscall[syscall]->end());
+
+ if(m_filter_by_syscall[syscall]->size() == 0)
+ {
+ delete m_filter_by_syscall[syscall];
+ m_filter_by_syscall[syscall] = NULL;
+ }
+ }
+ }
+ }
+}
+
+
+bool sinsp_evttype_filter::ruleset_filters::run(sinsp_evt *evt)
+{
+ list *filters;
+
+ uint16_t etype = evt->m_pevt->type;
+
+ if(etype == PPME_GENERIC_E || etype == PPME_GENERIC_X)
+ {
+ sinsp_evt_param *parinfo = evt->get_param(0);
+ ASSERT(parinfo->m_len == sizeof(uint16_t));
+ uint16_t evid = *(uint16_t *)parinfo->m_val;
+
+ filters = m_filter_by_syscall[evid];
+ }
+ else
+ {
+ filters = m_filter_by_evttype[etype];
+ }
+
+ if (!filters) {
+ return false;
+ }
+
+ for (auto &wrap : *filters)
+ {
+ if(wrap->filter->run(evt))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void sinsp_evttype_filter::ruleset_filters::evttypes_for_ruleset(std::vector &evttypes)
+{
+ evttypes.assign(PPM_EVENT_MAX+1, false);
+
+ for(uint32_t etype = 0; etype < PPM_EVENT_MAX; etype++)
+ {
+ list *filters = m_filter_by_evttype[etype];
+ if(filters)
+ {
+ evttypes[etype] = true;
+ }
+ }
}
-sinsp_evttype_filter::filter_wrapper::~filter_wrapper()
+void sinsp_evttype_filter::ruleset_filters::syscalls_for_ruleset(std::vector &syscalls)
{
+ syscalls.assign(PPM_SC_MAX+1, false);
+
+ for(uint32_t evid = 0; evid < PPM_SC_MAX; evid++)
+ {
+ list *filters = m_filter_by_syscall[evid];
+ if(filters)
+ {
+ syscalls[evid] = true;
+ }
+ }
}
+
void sinsp_evttype_filter::add(string &name,
set &evttypes,
set &syscalls,
@@ -2119,16 +2256,19 @@ void sinsp_evttype_filter::add(string &name,
sinsp_filter *filter)
{
filter_wrapper *wrap = new filter_wrapper();
- wrap->order = m_cur_order++;
wrap->filter = filter;
- wrap->evttypes.assign(PPM_EVENT_MAX+1, false);
+ // If no evttypes or syscalls are specified, the filter is
+ // enabled for all evttypes/syscalls.
+ bool def = ((evttypes.size() == 0 && syscalls.size() == 0) ? true : false);
+
+ wrap->evttypes.assign(PPM_EVENT_MAX+1, def);
for(auto &evttype : evttypes)
{
wrap->evttypes[evttype] = true;
}
- wrap->syscalls.assign(PPM_SC_MAX+1, false);
+ wrap->syscalls.assign(PPM_SC_MAX+1, def);
for(auto &syscall : syscalls)
{
wrap->syscalls[syscall] = true;
@@ -2136,38 +2276,6 @@ void sinsp_evttype_filter::add(string &name,
m_filters.insert(pair(name, wrap));
- if(evttypes.size() == 0 && syscalls.size() == 0)
- {
- m_catchall_filters.push_back(wrap);
- }
- else
- {
-
- for(const auto &evttype: evttypes)
- {
- list *filters = m_filter_by_evttype[evttype];
- if(filters == NULL)
- {
- filters = new list();
- m_filter_by_evttype[evttype] = filters;
- }
-
- filters->push_back(wrap);
- }
-
- for(const auto &syscall: syscalls)
- {
- list *filters = m_filter_by_syscall[syscall];
- if(filters == NULL)
- {
- filters = new list();
- m_filter_by_syscall[syscall] = filters;
- }
-
- filters->push_back(wrap);
- }
- }
-
for(const auto &tag: tags)
{
auto it = m_filter_by_tag.lower_bound(tag);
@@ -2187,165 +2295,68 @@ void sinsp_evttype_filter::enable(const string &pattern, bool enabled, uint16_t
{
regex re(pattern);
+ while (m_rulesets.size() < (size_t) ruleset + 1)
+ {
+ m_rulesets.push_back(new ruleset_filters());
+ }
+
for(const auto &val : m_filters)
{
if (regex_match(val.first, re))
{
- if(val.second->enabled.size() < (size_t) (ruleset + 1))
+ if(enabled)
+ {
+ m_rulesets[ruleset]->add_filter(val.second);
+ }
+ else
{
- val.second->enabled.resize(ruleset + 1);
+ m_rulesets[ruleset]->remove_filter(val.second);
}
- val.second->enabled[ruleset] = enabled;
}
}
}
void sinsp_evttype_filter::enable_tags(const set &tags, bool enabled, uint16_t ruleset)
{
- for(const auto &tag : tags)
+ while (m_rulesets.size() < (size_t) ruleset + 1)
{
- for(const auto &wrap : m_filter_by_tag[tag])
- {
- if(wrap->enabled.size() < (size_t) (ruleset + 1))
- {
- wrap->enabled.resize(ruleset + 1);
- }
- wrap->enabled[ruleset] = enabled;
- }
+ m_rulesets.push_back(new ruleset_filters());
}
-}
-bool sinsp_evttype_filter::check_filter(filter_wrapper *wrap,
- sinsp_evt *evt,
- uint16_t ruleset)
-{
- return (wrap->enabled.size() >= (size_t) (ruleset + 1) &&
- wrap->enabled[ruleset] &&
- wrap->filter->run(evt));
-}
-
-// Given two lists of filter_wrappers, consider all the
-// filter_wrappers ordered by wrap->order.
-bool sinsp_evttype_filter::check_filters(sinsp_evt *evt,
- uint16_t ruleset,
- std::list &la,
- std::list &lb)
-{
- for(auto ita = la.begin(), itb = lb.begin();
- ita != la.end() || itb != lb.end();
- /* */)
+ for(const auto &tag : tags)
{
- while(ita != la.end() &&
- (itb == lb.end() ||
- (*ita)->order < (*itb)->order))
+ for(const auto &wrap : m_filter_by_tag[tag])
{
- if(check_filter(*ita, evt, ruleset))
+ if(enabled)
{
- return true;
+ m_rulesets[ruleset]->add_filter(wrap);
}
- ita++;
- }
-
- while(itb != lb.end() &&
- (ita == la.end() ||
- (*itb)->order < (*ita)->order))
- {
- if(check_filter(*itb, evt, ruleset))
+ else
{
- return true;
+ m_rulesets[ruleset]->remove_filter(wrap);
}
- itb++;
}
}
-
- return false;
}
bool sinsp_evttype_filter::run(sinsp_evt *evt, uint16_t ruleset)
{
- uint16_t etype = evt->m_pevt->type;
-
- list *filters;
-
- if(etype == PPME_GENERIC_E || etype == PPME_GENERIC_X)
- {
- sinsp_evt_param *parinfo = evt->get_param(0);
- ASSERT(parinfo->m_len == sizeof(uint16_t));
- uint16_t evid = *(uint16_t *)parinfo->m_val;
-
- filters = m_filter_by_syscall[evid];
- }
- else
+ if(m_rulesets.size() < (size_t) ruleset + 1)
{
- filters = m_filter_by_evttype[etype];
- }
-
- list empty_list;
-
- if (!filters) {
- filters = &empty_list;
+ return false;
}
- return check_filters(evt, ruleset, *filters, m_catchall_filters);
-}
-
-
-// Solely used for code sharing in evttypes_for_rulset
-void sinsp_evttype_filter::check_filter_wrappers(std::vector &evttypes_syscalls,
- uint32_t idx,
- std::list &filters,
- uint16_t ruleset)
-{
- for(filter_wrapper *wrap : filters)
- {
- if(wrap->enabled.size() >= (size_t) (ruleset + 1) &&
- wrap->enabled[ruleset])
- {
- evttypes_syscalls[idx] = true;
- break;
- }
- }
+ return m_rulesets[ruleset]->run(evt);
}
void sinsp_evttype_filter::evttypes_for_ruleset(std::vector &evttypes, uint16_t ruleset)
{
- evttypes.assign(PPM_EVENT_MAX+1, false);
-
- for(uint32_t etype = 0; etype < PPM_EVENT_MAX; etype++)
- {
- // Catchall filters (ones that don't explicitly refer
- // to a type) must run for all event types.
- check_filter_wrappers(evttypes, etype, m_catchall_filters, ruleset);
-
- if(!evttypes[etype])
- {
- list *filters = m_filter_by_evttype[etype];
- if(filters)
- {
- check_filter_wrappers(evttypes, etype, *filters, ruleset);
- }
- }
- }
+ return m_rulesets[ruleset]->evttypes_for_ruleset(evttypes);
}
void sinsp_evttype_filter::syscalls_for_ruleset(std::vector &syscalls, uint16_t ruleset)
{
- syscalls.assign(PPM_SC_MAX+1, false);
-
- for(uint32_t evid = 0; evid < PPM_SC_MAX; evid++)
- {
- // Catchall filters (ones that don't explicitly refer
- // to a syscall) must run for all syscall numbers.
- check_filter_wrappers(syscalls, evid, m_catchall_filters, ruleset);
-
- if(!syscalls[evid])
- {
- list *filters = m_filter_by_syscall[evid];
- if(filters)
- {
- check_filter_wrappers(syscalls, evid, *filters, ruleset);
- }
- }
- }
+ return m_rulesets[ruleset]->syscalls_for_ruleset(syscalls);
}
+
#endif // HAS_FILTERING
diff --git a/userspace/libsinsp/filter.h b/userspace/libsinsp/filter.h
index 22f5940f7b..a76294d80c 100644
--- a/userspace/libsinsp/filter.h
+++ b/userspace/libsinsp/filter.h
@@ -214,11 +214,7 @@ class SINSP_PUBLIC sinsp_evttype_filter
private:
- class filter_wrapper {
- public:
- filter_wrapper();
- virtual ~filter_wrapper();
-
+ struct filter_wrapper {
sinsp_filter *filter;
// Indexes from event type to enabled/disabled.
@@ -226,59 +222,42 @@ class SINSP_PUBLIC sinsp_evttype_filter
// Indexes from syscall code to enabled/disabled.
std::vector syscalls;
-
- // Indexes from ruleset to enabled/disabled. Unlike
- // m_filter_by_evttype, this is managed as a vector as we're
- // expecting ruleset ids that are small and grouped in the range
- // 0..k, as compared to all possible event types.
- std::vector enabled;
-
- // An ordering number, used to ensure that filters are
- // always run in the order that they were added to
- // this object. Specifically, this is used between the
- // catchall list and the per-eventtype/per-syscallnum
- // lists.
- uint64_t order;
};
- bool check_filter(filter_wrapper *wrap,
- sinsp_evt *evt,
- uint16_t ruleset);
+ // A group of filters all having the same ruleset
+ class ruleset_filters {
+ public:
+ ruleset_filters();
+
+ virtual ~ruleset_filters();
- bool check_filters(sinsp_evt *evt,
- uint16_t ruleset,
- std::list &la,
- std::list &lb);
+ void add_filter(filter_wrapper *wrap);
+ void remove_filter(filter_wrapper *wrap);
- // Solely used for code sharing in evttypes_for_ruleset/syscalls_for_ruleset
- void check_filter_wrappers(std::vector &evttypes_syscalls,
- uint32_t idx,
- std::list &filters,
- uint16_t ruleset);
+ bool run(sinsp_evt *evt);
- // Maps from event type to filter. There can be multiple
- // filters per event type.
- std::list *m_filter_by_evttype[PPM_EVENT_MAX];
+ void evttypes_for_ruleset(std::vector &evttypes);
- // Maps from syscall number to filter. There can be multiple
- // filters per syscall number
- std::list *m_filter_by_syscall[PPM_SC_MAX];
+ void syscalls_for_ruleset(std::vector &syscalls);
- // It's possible to add an event type filter with an empty
- // list of event types/syscall numbers, meaning it should run
- // for all event types/syscalls.
- std::list m_catchall_filters;
+ private:
+ // Maps from event type to filter. There can be multiple
+ // filters per event type.
+ std::list *m_filter_by_evttype[PPM_EVENT_MAX];
+
+ // Maps from syscall number to filter. There can be multiple
+ // filters per syscall number
+ std::list *m_filter_by_syscall[PPM_SC_MAX];
+ };
+
+ std::vector m_rulesets;
// Maps from tag to list of filters having that tag.
std::map> m_filter_by_tag;
- // This holds all the filters in
- // m_filter_by_evttype/m_catchall_evttype_filters, so they can
+ // This holds all the filters passed to add(), so they can
// be cleaned up.
-
map m_filters;
-
- uint64_t m_cur_order;
};
/*@}*/
diff --git a/userspace/libsinsp/prefix_search.h b/userspace/libsinsp/prefix_search.h
index 6431817d5e..0f0f984c5b 100644
--- a/userspace/libsinsp/prefix_search.h
+++ b/userspace/libsinsp/prefix_search.h
@@ -183,6 +183,7 @@ void path_prefix_map::add_search_path_components(const path_prefix_map_ut
// can drop the existing subtree. For example, we can
// drop /usr/lib when adding /usr.
delete(it->second.first);
+ delete(it->second.second);
m_dirs.erase(*cur);
m_dirs[*cur] = std::pair(NULL, new Value(v));
}