Skip to content

Commit

Permalink
Preserve order between catchall & other filters
Browse files Browse the repository at this point in the history
Previously, catchall filters were always matched against an event first,
followed by any filters specificially linked to that event's type. This
didn't preserve the order of filters as they appeared in the file,
though.

Instead, assign a filter order for each filter and walk the catchall and
evttype-specific filters in order, trying to match each against the
event.

This fixes falcosecurity/falco#354.
  • Loading branch information
mstemm committed Apr 18, 2018
1 parent b5ce0de commit c10f1e1
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 22 deletions.
70 changes: 48 additions & 22 deletions userspace/libsinsp/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2067,6 +2067,7 @@ 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<sinsp_filter *> *));
memset(m_filter_by_syscall, 0, PPM_SC_MAX * sizeof(list<sinsp_filter *> *));
Expand Down Expand Up @@ -2118,6 +2119,7 @@ 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);
Expand Down Expand Up @@ -2213,23 +2215,54 @@ void sinsp_evttype_filter::enable_tags(const set<string> &tags, bool enabled, ui
}
}

bool sinsp_evttype_filter::run(sinsp_evt *evt, uint16_t ruleset)
bool sinsp_evttype_filter::check_filter(filter_wrapper *wrap,
sinsp_evt *evt,
uint16_t ruleset)
{
//
// First run any catchall event type filters (ones that did not
// explicitly specify any event type.
//
for(filter_wrapper *wrap : m_catchall_filters)
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<filter_wrapper *> &la,
std::list<filter_wrapper *> &lb)
{
for(auto ita = la.begin(), itb = lb.begin();
ita != la.end() || itb != lb.end();
/* */)
{
if(wrap->enabled.size() >= (size_t) (ruleset + 1) &&
wrap->enabled[ruleset] &&
wrap->filter->run(evt))
while(ita != la.end() &&
(itb == lb.end() ||
(*ita)->order < (*itb)->order))
{
return true;
if(check_filter(*ita, evt, ruleset))
{
return true;
}
ita++;
}

while(itb != lb.end() &&
(ita == la.end() ||
(*itb)->order < (*ita)->order))
{
if(check_filter(*itb, evt, ruleset))
{
return true;
}
itb++;
}
}

return false;
}

bool sinsp_evttype_filter::run(sinsp_evt *evt, uint16_t ruleset)
{
uint16_t etype = evt->m_pevt->type;

list<filter_wrapper *> *filters;
Expand All @@ -2247,20 +2280,13 @@ bool sinsp_evttype_filter::run(sinsp_evt *evt, uint16_t ruleset)
filters = m_filter_by_evttype[etype];
}

if(filters)
{
for(filter_wrapper *wrap : *filters)
{
if(wrap->enabled.size() >= (size_t) (ruleset + 1) &&
wrap->enabled[ruleset] &&
wrap->filter->run(evt))
{
return true;
}
}
list<filter_wrapper *> empty_list;

if (!filters) {
filters = &empty_list;
}

return false;
return check_filters(evt, ruleset, *filters, m_catchall_filters);
}


Expand Down
18 changes: 18 additions & 0 deletions userspace/libsinsp/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,24 @@ class SINSP_PUBLIC sinsp_evttype_filter
// expecting ruleset ids that are small and grouped in the range
// 0..k, as compared to all possible event types.
std::vector<bool> 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);

bool check_filters(sinsp_evt *evt,
uint16_t ruleset,
std::list<filter_wrapper *> &la,
std::list<filter_wrapper *> &lb);

// Solely used for code sharing in evttypes_for_ruleset/syscalls_for_ruleset
void check_filter_wrappers(std::vector<bool> &evttypes_syscalls,
uint32_t idx,
Expand Down Expand Up @@ -261,6 +277,8 @@ class SINSP_PUBLIC sinsp_evttype_filter
// be cleaned up.

map<std::string,filter_wrapper *> m_filters;

uint64_t m_cur_order;
};

/*@}*/
Expand Down

0 comments on commit c10f1e1

Please sign in to comment.