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)); }