-
Notifications
You must be signed in to change notification settings - Fork 171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(userspace/libsinsp): let plugins parse events before eventually filtering them out through inspector global filter #2182
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ class sinsp_parser { | |
void process_event(sinsp_evt* evt); | ||
void event_cleanup(sinsp_evt* evt); | ||
|
||
bool reset(sinsp_evt* evt); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since it is now called by sinsp, moved to public. |
||
void erase_fd(erase_fd_params* params); | ||
|
||
// | ||
|
@@ -57,7 +58,6 @@ class sinsp_parser { | |
// | ||
// Helpers | ||
// | ||
bool reset(sinsp_evt* evt); | ||
inline void store_event(sinsp_evt* evt); | ||
|
||
// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,79 @@ | |
*/ | ||
#define DEFAULT_ASYNC_EVENT_QUEUE_SIZE 1000 | ||
|
||
// Small sinsp event filter wrapper logic | ||
// that uses RAII to eventually filter out events. | ||
struct sinsp_evt_filter { | ||
bool do_filter_later; | ||
sinsp_evt* evt; | ||
|
||
explicit sinsp_evt_filter(sinsp_evt* e): do_filter_later(false), evt(e) { | ||
// | ||
// Filtering | ||
// | ||
const auto inspector = evt->get_inspector(); | ||
const bool is_live = inspector->is_live() || inspector->is_syscall_plugin(); | ||
const uint16_t etype = evt->get_type(); | ||
|
||
evt->set_filtered_out(false); | ||
|
||
// | ||
// When debug mode is not enabled, filter out events about itself | ||
// | ||
if(is_live && !inspector->is_debug_enabled()) { | ||
if(evt->get_tid() == inspector->m_self_pid && etype != PPME_SCHEDSWITCH_1_E && | ||
etype != PPME_SCHEDSWITCH_6_E && etype != PPME_DROP_E && etype != PPME_DROP_X && | ||
etype != PPME_SCAPEVENT_E && etype != PPME_PROCINFO_E && | ||
etype != PPME_CPU_HOTPLUG_E && inspector->m_self_pid) { | ||
evt->set_filtered_out(true); | ||
return; | ||
} | ||
} | ||
|
||
if(inspector->m_filter) { | ||
ppm_event_flags eflags = evt->get_info_flags(); | ||
if(eflags & EF_MODIFIES_STATE) { | ||
do_filter_later = true; | ||
} else { | ||
if(!inspector->run_filters_on_evt(evt)) { | ||
if(evt->get_tinfo() != NULL) { | ||
if(!(eflags & EF_SKIPPARSERESET || etype == PPME_SCHEDSWITCH_6_E)) { | ||
evt->get_tinfo()->set_lastevent_type(PPM_EVENT_MAX); | ||
} | ||
} | ||
evt->set_filtered_out(true); | ||
} | ||
} | ||
} | ||
} | ||
|
||
~sinsp_evt_filter() { | ||
// | ||
// With some state-changing events like clone, execve and open, we do the | ||
// filtering after having updated the state | ||
// | ||
const auto inspector = evt->get_inspector(); | ||
if(do_filter_later) { | ||
if(!inspector->run_filters_on_evt(evt)) { | ||
evt->set_filtered_out(true); | ||
return; | ||
} | ||
evt->set_filtered_out(false); | ||
} | ||
|
||
// | ||
// Offline captures can produce events with the SCAP_DF_STATE_ONLY. They are | ||
// supposed to go through the engine, but they must be filtered out before | ||
// reaching the user. | ||
// | ||
if(inspector->is_capture()) { | ||
if(evt->get_dump_flags() & SCAP_DF_STATE_ONLY) { | ||
evt->set_filtered_out(true); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
int32_t on_new_entry_from_proc(void* context, | ||
char* error, | ||
int64_t tid, | ||
|
@@ -1216,19 +1289,32 @@ | |
} | ||
|
||
// | ||
// Run the state engine | ||
// Cleanup the event-related state | ||
// | ||
m_parser->process_event(evt); | ||
m_parser->reset(evt); | ||
|
||
// run plugin-implemented parsers | ||
// note: we run the parsers even if the event has been filtered out, | ||
// because we have no guarantee that the plugin parsers will not use a given | ||
// event for state updates. Sinsp understands this through the | ||
// EF_MODIFIES_STATE flag, which however is only relevant in the context of | ||
// the internal implementation of libsinsp. | ||
for(auto& pp : m_plugin_parsers) { | ||
// todo(jason): should we log parsing errors here? | ||
pp.process_event(evt, m_event_sources); | ||
// Since evt_filter object below uses RAII, create a new scope. | ||
{ | ||
// Object that uses RAII to enable event filtered out flag | ||
sinsp_evt_filter evt_filter(evt); | ||
|
||
if(!evt->is_filtered_out()) { | ||
// | ||
// Run the state engine | ||
// | ||
m_parser->process_event(evt); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keep old behavior: only process event by sinsp if the event has not been filtered out. |
||
} | ||
|
||
// run plugin-implemented parsers | ||
// note: we run the parsers even if the event has been filtered out, | ||
// because we have no guarantee that the plugin parsers will not use a given | ||
// event for state updates. Sinsp understands this through the | ||
// EF_MODIFIES_STATE flag, which however is only relevant in the context of | ||
// the internal implementation of libsinsp. | ||
for(auto& pp : m_plugin_parsers) { | ||
// todo(jason): should we log parsing errors here? | ||
pp.process_event(evt, m_event_sources); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For plugins, as stated by the comment, we cannot know in advance if an event will modify its state; therefore always call the plugin parsers. |
||
} | ||
} | ||
|
||
// Finally set output evt; | ||
|
@@ -1536,7 +1622,7 @@ | |
return m_filterstring; | ||
} | ||
|
||
bool sinsp::run_filters_on_evt(sinsp_evt* evt) { | ||
bool sinsp::run_filters_on_evt(sinsp_evt* evt) const { | ||
// | ||
// First run the global filter, if there is one. | ||
// | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now the parser is only responsible for the big switch case (ie: the actual parsing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of the code below has been moved to a RAII oriented structure under sinsp.h: struct sinsp_evt_filter.