Skip to content

Commit

Permalink
Detect loops in parent thread state
Browse files Browse the repository at this point in the history
sinsp_threadinfo::detect_parent_state_loop() detects a loop in the
parent state by using two pointers that traverse the parent state at
different rates. If they ever match each other, it detects a loop.

In all the places where filterchecks might traverse parent state in an
unbounded way, first check for a loop in parent state and return
NULL/false if a loop is detected.

This prevents infinite loops like observed in
falcosecurity/falco#208.

This doesn't address the underlying cause of what caused the thread
state to get corrupted in the first place. That's tracked by a separate
issue #752.
  • Loading branch information
mstemm committed Feb 14, 2017
1 parent 355a184 commit e5f3337
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
20 changes: 20 additions & 0 deletions userspace/libsinsp/filterchecks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,11 @@ uint8_t* sinsp_filter_check_thread::extract(sinsp_evt *evt, OUT uint32_t* len, b
return NULL;
}

if(mt->detect_parent_state_loop())
{
return NULL;
}

for(pt = mt->get_parent_thread();
pt != NULL && pt->m_sid == mt->m_sid;
mt = pt, pt = pt->get_parent_thread());
Expand Down Expand Up @@ -1916,6 +1921,11 @@ uint8_t* sinsp_filter_check_thread::extract(sinsp_evt *evt, OUT uint32_t* len, b
}
}

if(mt->detect_parent_state_loop())
{
return NULL;
}

for(; mt != NULL; mt = mt->get_parent_thread())
{
size_t len = mt->m_comm.size();
Expand Down Expand Up @@ -2169,6 +2179,11 @@ bool sinsp_filter_check_thread::compare_full_apid(sinsp_evt *evt)
//
// No id specified, search in all of the ancestors
//
if(mt->detect_parent_state_loop())
{
return false;
}

for(j = 0; mt != NULL; mt = mt->get_parent_thread(), j++)
{
if(j > 0)
Expand Down Expand Up @@ -2218,6 +2233,11 @@ bool sinsp_filter_check_thread::compare_full_aname(sinsp_evt *evt)
//
// No id specified, search in all of the ancestors
//
if(mt->detect_parent_state_loop())
{
return false;
}

for(j = 0; mt != NULL; mt = mt->get_parent_thread(), j++)
{
if(j > 0)
Expand Down
30 changes: 30 additions & 0 deletions userspace/libsinsp/threadinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ void sinsp_threadinfo::init()
m_program_hash = 0;
m_program_hash_falco = 0;
m_lastevent_data = NULL;
m_parent_loop_detected = false;
}

sinsp_threadinfo::~sinsp_threadinfo()
Expand Down Expand Up @@ -767,6 +768,35 @@ uint64_t sinsp_threadinfo::get_fd_limit()
return get_main_thread()->m_fdlimit;
}

bool sinsp_threadinfo::detect_parent_state_loop()
{
// Use two pointers starting at this, traversing the parent
// state, at different rates. If they ever equal each other
// before one is NULL there's a loop.
sinsp_threadinfo *p1=this, *p2=this;

while(p1 && p2 && p2->get_parent_thread())
{
p1 = p1->get_parent_thread();
p2 = p2->get_parent_thread()->get_parent_thread();

if (p1 && (p1 == p2))
{
// Note we only log a loop once for a given main thread, to avoid flooding logs.
if(!m_parent_loop_detected)
{
g_logger.log(string("Loop in parent thread state detected for pid ") +
std::to_string(m_pid), sinsp_logger::SEV_WARNING);
m_parent_loop_detected = true;
}

return true;
}
}

return false;
}

sinsp_threadinfo* sinsp_threadinfo::lookup_thread()
{
return m_inspector->get_thread(m_pid, true, true);
Expand Down
6 changes: 6 additions & 0 deletions userspace/libsinsp/threadinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ class SINSP_PUBLIC sinsp_threadinfo
*/
uint64_t get_fd_limit();

//
// Determine whether or not this thread has a loop in its parent state
//
bool detect_parent_state_loop();

//
// Core state
//
Expand Down Expand Up @@ -325,6 +330,7 @@ VISIBILITY_PRIVATE
uint16_t m_lastevent_type;
uint16_t m_lastevent_cpuid;
sinsp_evt::category m_lastevent_category;
bool m_parent_loop_detected;

friend class sinsp;
friend class sinsp_parser;
Expand Down

0 comments on commit e5f3337

Please sign in to comment.