Skip to content

Commit

Permalink
Allow multiple filters (#627)
Browse files Browse the repository at this point in the history
* Whitespace diffs.

Putting whitespace changes in a separate commit.

* Add optional support for multiple filters.

Add support for an additional set of individual filters that can run
alongside the main filter set in sinsp::set_filter(). Each additional
filter comes with a list of event types for which the filter should run.

sinsp::add_evttype_filter adds an event type filter to the inspector. It
provides a list of event types and a sinsp_filter pointer. The list of
event types can be empty, implying the filter is a catchall filter and
should run for all event types. This does not replace the main function
set_filter()--the idea is that you can specify a global filter as well
as per-event type filters. Both will run for all events.

An array m_filter_by_evttype maps from event type to a list of
sinsp_filter pointers. Each list at index i holds the filters that
should run for events with type i. A filter can run for multiple event
types, so the sinsp_filter pointers can appear in multiple lists.

There's a separate list m_catchall_evttype_filters that contains filters
that should run for all event types.

The individual filter pointers are also held in a list m_evttype_filters
so they can be cleaned up on close().

A new method run_filters_on_evt() handles the details of running the
main filter, catchall filters, and the individual filters. It finds the
filters related to the event's type, and runs those filters.

Falco uses the lua callbacks in lua_parser{_api} to populate filters as
the lua code parses the rule's condition, so also modify lua_parser to
add a optional flag to get_parser that steals the m_filter object and
creates a new one. Falco calls get_parser for each rule's condition,
which allows it to create a sinsp_filter object for each rule.
  • Loading branch information
mstemm committed Jul 18, 2016
1 parent abf11d8 commit a7a8b59
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 54 deletions.
27 changes: 20 additions & 7 deletions userspace/libsinsp/lua_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ lua_parser::lua_parser(sinsp* inspector, lua_State *ls)
m_inspector = inspector;

m_ls = ls;
m_have_rel_expr = false;
m_last_boolop = BO_NONE;
m_nest_level = 0;

m_filter = new sinsp_filter(m_inspector);
reset();

// Register our c++ defined functions
luaL_openlib(m_ls, "filter", ll_filter, 0);
Expand All @@ -41,13 +37,30 @@ lua_parser::lua_parser(sinsp* inspector, lua_State *ls)

}

sinsp_filter* lua_parser::get_filter()
void lua_parser::reset()
{
m_have_rel_expr = false;
m_last_boolop = BO_NONE;
m_nest_level = 0;

m_filter = new sinsp_filter(m_inspector);
}

sinsp_filter* lua_parser::get_filter(bool reset_filter)
{
if (m_nest_level != 0)
{
throw sinsp_exception("Error in configured filter: unbalanced nesting");
}
return m_filter;

sinsp_filter *ret = m_filter;

if (reset_filter)
{
reset();
}

return ret;
}
lua_parser::~lua_parser()
{
Expand Down
4 changes: 3 additions & 1 deletion userspace/libsinsp/lua_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ class lua_parser
public:
lua_parser(sinsp* inspector, lua_State *ls);
~lua_parser();
sinsp_filter* get_filter();
sinsp_filter* get_filter(bool reset_filter = false);

private:

void reset();
sinsp* m_inspector;

sinsp_filter* m_filter;
Expand Down
13 changes: 5 additions & 8 deletions userspace/libsinsp/parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ void sinsp_parser::process_event(sinsp_evt *evt)
#if defined(HAS_FILTERING) && defined(HAS_CAPTURE_FILTERING)
bool do_filter_later = false;

if(m_inspector->m_filter)
if(m_inspector->m_filter || m_inspector->m_evttype_filters.size() > 0)
{
ppm_event_flags eflags = evt->get_info_flags();

Expand Down Expand Up @@ -230,7 +230,7 @@ void sinsp_parser::process_event(sinsp_evt *evt)
}
else
{
if(m_inspector->m_filter->run(evt) == false)
if(m_inspector->run_filters_on_evt(evt) == false)
{
if(evt->m_tinfo != NULL)
{
Expand Down Expand Up @@ -468,13 +468,10 @@ void sinsp_parser::process_event(sinsp_evt *evt)
#if defined(HAS_FILTERING) && defined(HAS_CAPTURE_FILTERING)
if(do_filter_later)
{
if(m_inspector->m_filter)
if(m_inspector->run_filters_on_evt(evt) == false)
{
if(m_inspector->m_filter->run(evt) == false)
{
evt->m_filtered_out = true;
return;
}
evt->m_filtered_out = true;
return;
}
evt->m_filtered_out = false;
}
Expand Down
120 changes: 100 additions & 20 deletions userspace/libsinsp/sinsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ extern sinsp_evttables g_infotables;
extern vector<chiseldir_info>* g_chisel_dirs;
#endif

void on_new_entry_from_proc(void* context, int64_t tid, scap_threadinfo* tinfo,
scap_fdinfo* fdinfo, scap_t* newhandle);
void on_new_entry_from_proc(void* context, int64_t tid, scap_threadinfo* tinfo,
scap_fdinfo* fdinfo, scap_t* newhandle);

///////////////////////////////////////////////////////////////////////////////
// sinsp implementation
Expand Down Expand Up @@ -201,7 +201,7 @@ void sinsp::filter_proc_table_when_saving(bool filter)

if(m_h != NULL)
{
scap_set_refresh_proc_table_when_saving(m_h, !filter);
scap_set_refresh_proc_table_when_saving(m_h, !filter);
}
}

Expand Down Expand Up @@ -253,7 +253,7 @@ void sinsp::init()
delete m_cycle_writer;
m_cycle_writer = NULL;
}

m_cycle_writer = new cycle_writer(this->is_live());

//
Expand Down Expand Up @@ -549,6 +549,23 @@ void sinsp::close()
delete m_filter;
m_filter = NULL;
}

for(int i = 0; i < PPM_EVENT_MAX; i++)
{
if(m_filter_by_evttype[i])
{
delete m_filter_by_evttype[i];
m_filter_by_evttype[i] = NULL;
}
}

m_catchall_evttype_filters.clear();

for(auto filter : m_evttype_filters)
{
delete filter;
}
m_evttype_filters.clear();
#endif
}

Expand Down Expand Up @@ -596,9 +613,9 @@ void sinsp::autodump_stop()
}
}

void sinsp::on_new_entry_from_proc(void* context,
int64_t tid,
scap_threadinfo* tinfo,
void sinsp::on_new_entry_from_proc(void* context,
int64_t tid,
scap_threadinfo* tinfo,
scap_fdinfo* fdinfo,
scap_t* newhandle)
{
Expand Down Expand Up @@ -655,9 +672,9 @@ void sinsp::on_new_entry_from_proc(void* context,
}
}

void on_new_entry_from_proc(void* context,
int64_t tid,
scap_threadinfo* tinfo,
void on_new_entry_from_proc(void* context,
int64_t tid,
scap_threadinfo* tinfo,
scap_fdinfo* fdinfo,
scap_t* newhandle)
{
Expand Down Expand Up @@ -799,7 +816,7 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
int32_t res;

//
// Check if there are fake cpu events to events
// Check if there are fake cpu events to events
//
if(m_metaevt != NULL)
{
Expand Down Expand Up @@ -899,7 +916,7 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
if(procrequest_tod - m_last_procrequest_tod > ONE_SECOND_IN_NS / 2)
{
m_last_procrequest_tod = procrequest_tod;
m_next_flush_time_ns = ts - (ts % ONE_SECOND_IN_NS) + ONE_SECOND_IN_NS;
m_next_flush_time_ns = ts - (ts % ONE_SECOND_IN_NS) + ONE_SECOND_IN_NS;

m_meinfo.m_pli = scap_get_threadlist_from_driver(m_h);
if(m_meinfo.m_pli == NULL)
Expand Down Expand Up @@ -1038,7 +1055,7 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)

#if defined(HAS_FILTERING) && defined(HAS_CAPTURE_FILTERING)
scap_dump_flags dflags;

bool do_drop;
dflags = evt->get_dump_flags(&do_drop);
if(do_drop)
Expand Down Expand Up @@ -1120,7 +1137,7 @@ int32_t sinsp::next(OUT sinsp_evt **puevt)
//
// Update the last event time for this thread
//
if(evt->m_tinfo &&
if(evt->m_tinfo &&
evt->get_type() != PPME_SCHEDSWITCH_1_E &&
evt->get_type() != PPME_SCHEDSWITCH_6_E)
{
Expand Down Expand Up @@ -1216,7 +1233,7 @@ sinsp_threadinfo* sinsp::get_thread(int64_t tid, bool query_os_if_not_found, boo

//
// Since this thread is created out of thin air, we need to
// properly set its reference count, by scanning the table
// properly set its reference count, by scanning the table
//
threadinfo_map_t* pttable = &m_thread_manager->m_threadtable;
threadinfo_map_iterator_t it;
Expand Down Expand Up @@ -1351,6 +1368,69 @@ const string sinsp::get_filter()
return m_filterstring;
}

void sinsp::add_evttype_filter(list<uint32_t> &evttypes,
sinsp_filter *filter)
{
m_evttype_filters.push_back(filter);

if(evttypes.size() == 0)
{
m_catchall_evttype_filters.push_back(filter);
}
else
{

for(auto evttype: evttypes)
{
list<sinsp_filter *> *filters = m_filter_by_evttype[evttype];
if(filters == NULL)
{
filters = new list<sinsp_filter*>();
m_filter_by_evttype[evttype] = filters;
}

filters->push_back(filter);
}
}
}

bool sinsp::run_filters_on_evt(sinsp_evt *evt)
{
//
// First run the global filter, if there is one.
//
if(m_filter && m_filter->run(evt) == true)
{
return true;
}

//
// Then run any catchall event type filters (ones that did not
// explicitly specify any event type.
//
for(sinsp_filter *filt : m_catchall_evttype_filters)
{
if(filt->run(evt) == true)
{
return true;
}
}

list<sinsp_filter *> *filters = m_filter_by_evttype[evt->m_pevt->type];

if(filters)
{
for(sinsp_filter *filt : *filters)
{
if(filt->run(evt) == true)
{
return true;
}
}
}

return false;
}
#endif

const scap_machine_info* sinsp::get_machine_info()
Expand Down Expand Up @@ -1808,17 +1888,17 @@ bool sinsp_thread_manager::remove_inactive_threads()
//
if(m_inspector->m_inactive_thread_scan_time_ns > 30 * ONE_SECOND_IN_NS)
{
m_last_flush_time_ns =
m_last_flush_time_ns =
(m_inspector->m_lastevent_ts - m_inspector->m_inactive_thread_scan_time_ns + 30 * ONE_SECOND_IN_NS);
}
else
{
m_last_flush_time_ns =
(m_inspector->m_lastevent_ts - m_inspector->m_inactive_thread_scan_time_ns);
m_last_flush_time_ns =
(m_inspector->m_lastevent_ts - m_inspector->m_inactive_thread_scan_time_ns);
}
}

if(m_inspector->m_lastevent_ts >
if(m_inspector->m_lastevent_ts >
m_last_flush_time_ns + m_inspector->m_inactive_thread_scan_time_ns)
{
res = true;
Expand All @@ -1834,7 +1914,7 @@ bool sinsp_thread_manager::remove_inactive_threads()
{
bool closed = (it->second.m_flags & PPM_CL_CLOSED) != 0;

if(closed ||
if(closed ||
((m_inspector->m_lastevent_ts > it->second.m_lastaccess_ts + m_inspector->m_thread_timeout_ns) &&
!scap_is_thread_alive(m_inspector->m_h, it->second.m_pid, it->first, it->second.m_comm.c_str()))
)
Expand Down
Loading

0 comments on commit a7a8b59

Please sign in to comment.