diff --git a/userspace/libsinsp/lua_parser.cpp b/userspace/libsinsp/lua_parser.cpp index d83389a07d..25bdebdab0 100644 --- a/userspace/libsinsp/lua_parser.cpp +++ b/userspace/libsinsp/lua_parser.cpp @@ -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); @@ -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() { diff --git a/userspace/libsinsp/lua_parser.h b/userspace/libsinsp/lua_parser.h index 330e9c0e66..5a9e3e514f 100644 --- a/userspace/libsinsp/lua_parser.h +++ b/userspace/libsinsp/lua_parser.h @@ -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; diff --git a/userspace/libsinsp/parsers.cpp b/userspace/libsinsp/parsers.cpp index bddc1b1a5d..b40f702782 100644 --- a/userspace/libsinsp/parsers.cpp +++ b/userspace/libsinsp/parsers.cpp @@ -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(); @@ -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) { @@ -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; } diff --git a/userspace/libsinsp/sinsp.cpp b/userspace/libsinsp/sinsp.cpp index f4ec9aa1e0..dbbaa49138 100644 --- a/userspace/libsinsp/sinsp.cpp +++ b/userspace/libsinsp/sinsp.cpp @@ -45,8 +45,8 @@ extern sinsp_evttables g_infotables; extern vector* 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 @@ -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); } } @@ -253,7 +253,7 @@ void sinsp::init() delete m_cycle_writer; m_cycle_writer = NULL; } - + m_cycle_writer = new cycle_writer(this->is_live()); // @@ -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 } @@ -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) { @@ -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) { @@ -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) { @@ -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) @@ -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) @@ -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) { @@ -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; @@ -1351,6 +1368,69 @@ const string sinsp::get_filter() return m_filterstring; } +void sinsp::add_evttype_filter(list &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 *filters = m_filter_by_evttype[evttype]; + if(filters == NULL) + { + filters = new list(); + 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 *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() @@ -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; @@ -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())) ) diff --git a/userspace/libsinsp/sinsp.h b/userspace/libsinsp/sinsp.h index 1a2d34906b..d4358519a8 100644 --- a/userspace/libsinsp/sinsp.h +++ b/userspace/libsinsp/sinsp.h @@ -293,10 +293,10 @@ class SINSP_PUBLIC sinsp \brief Determine if this inspector is going to load user tables on startup. - \param import_users if true, no user tables will be created for - this capture. This also means that no user or group info will be - written to the tracefile by the -w flag. The user/group tables are - necessary to use filter fields like user.name or group.name. However, + \param import_users if true, no user tables will be created for + this capture. This also means that no user or group info will be + written to the tracefile by the -w flag. The user/group tables are + necessary to use filter fields like user.name or group.name. However, creating them can increase sysdig's startup time. Moreover, they contain information that could be privacy sensitive. @@ -345,10 +345,15 @@ class SINSP_PUBLIC sinsp /*! \brief Return the filter set for this capture. - \return the filter previously set with \ref set_filter(), or an empty + \return the filter previously set with \ref set_filter(), or an empty string if no filter has been set yet. */ const string get_filter(); + + void add_evttype_filter(list &evttypes, + sinsp_filter* filter); + + bool run_filters_on_evt(sinsp_evt *evt); #endif /*! @@ -393,7 +398,7 @@ class SINSP_PUBLIC sinsp of failure. */ void autodump_start(const string& dump_filename, bool compress); - + /*! \brief Cycles the file pointer to a new capture file */ @@ -522,8 +527,8 @@ class SINSP_PUBLIC sinsp /*! \brief Add a new directory containing chisels. - \parame front_add if true, the chisel directory is added at the front of - the search list and therefore gets priority. + \parame front_add if true, the chisel directory is added at the front of + the search list and therefore gets priority. \note This function is not reentrant. */ @@ -572,7 +577,7 @@ class SINSP_PUBLIC sinsp /*! \brief Set the fatfile mode when writing events to file. - \note fatfile mode involves saving "hidden" events in the trace file + \note fatfile mode involves saving "hidden" events in the trace file that make it possible to preserve full state even when filters that would drop state packets are used during the capture. */ @@ -583,7 +588,7 @@ class SINSP_PUBLIC sinsp \note Sysdig can use the system library functions getservbyport and so to resolve protocol names and domain names. - + \param enable If set to false it will enable this function and use plain numerical values. */ @@ -603,7 +608,7 @@ class SINSP_PUBLIC sinsp } /*! - \brief Sets the max length of event argument strings. + \brief Sets the max length of event argument strings. \param len Max length after which an avent argument string is truncated. 0 means no limit. Use this to reduce verbosity when printing event info @@ -622,7 +627,7 @@ class SINSP_PUBLIC sinsp /*! \brief Set a flag indicating if the command line requested to show container information. - \param set true if the command line arugment is set to show container information + \param set true if the command line arugment is set to show container information */ void set_print_container_data(bool print_container_data); @@ -675,7 +680,7 @@ class SINSP_PUBLIC sinsp // void stop_dropping_mode(); void start_dropping_mode(uint32_t sampling_ratio); - 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); void set_get_procs_cpu_from_driver(bool get_procs_cpu_from_driver) { @@ -728,7 +733,7 @@ VISIBILITY_PRIVATE void remove_thread(int64_t tid, bool force); // // Note: lookup_only should be used when the query for the thread is made - // not as a consequence of an event for that thread arriving, but + // not as a consequence of an event for that thread arriving, but // just for lookup reason. In that case, m_lastaccess_ts is not updated // and m_last_tinfo is not set. // @@ -849,6 +854,20 @@ VISIBILITY_PRIVATE uint64_t m_firstevent_ts; sinsp_filter* m_filter; string m_filterstring; + + // Maps from event type to filter. There can be multiple + // filters per event type. + list *m_filter_by_evttype[PPM_EVENT_MAX]; + + // It's possible to add an event type filter with an empty + // list of event types, meaning it should run for all event + // types. + list m_catchall_evttype_filters; + + // This holds all the filters in + // m_filter_by_evttype/m_catchall_evttype_filters, so they can + // be cleaned up. + list m_evttype_filters; #endif // @@ -909,7 +928,7 @@ VISIBILITY_PRIVATE #endif // - // App events + // App events // bool m_track_tracers_state; list m_partial_tracers_list; @@ -923,9 +942,9 @@ VISIBILITY_PRIVATE // // Containers meta event management // - sinsp_evt m_meta_evt; // XXX this should go away - char* m_meta_evt_buf; // XXX this should go away - bool m_meta_evt_pending; // XXX this should go away + sinsp_evt m_meta_evt; // XXX this should go away + char* m_meta_evt_buf; // XXX this should go away + bool m_meta_evt_pending; // XXX this should go away sinsp_evt* m_metaevt; sinsp_evt* m_skipped_evt; meta_event_callback m_meta_event_callback;