Skip to content

Commit

Permalink
cleanup(libsinsp): add extract_leader_attribute_thread_hierarchy helper
Browse files Browse the repository at this point in the history
Signed-off-by: Melissa Kilby <[email protected]>
  • Loading branch information
incertum committed Jan 20, 2024
1 parent 4d205aa commit df1a23a
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 228 deletions.
232 changes: 6 additions & 226 deletions userspace/libsinsp/sinsp_filtercheck_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,253 +640,33 @@ uint8_t* sinsp_filter_check_thread::extract(sinsp_evt *evt, OUT uint32_t* len, b
RETURN_EXTRACT_VAR(tinfo->m_vpgid);
case TYPE_SNAME:
{
int64_t sid = tinfo->m_sid;

if(!tinfo->is_in_pid_namespace())
{
// Relying on the convention that a session id is the process id of the session leader.
// `threadinfo` lookup only applies when the process is running on the host and not in a pid
// namespace. However, if the process is running in a pid namespace, we instead traverse the process
// lineage until we find a match.
sinsp_threadinfo* sinfo = m_inspector->get_thread_ref(sid, false, true).get();
if(sinfo != NULL)
{
m_tstr = sinfo->get_comm();
RETURN_EXTRACT_STRING(m_tstr);
}
}

// This can occur when the session leader process has exited or if the process
// is running in a pid namespace and we only have the virtual session id, as
// seen from its pid namespace.
// Find the highest ancestor process that has the same session id and
// declare it to be the session leader.
sinsp_threadinfo* session_leader = tinfo;

sinsp_threadinfo::visitor_func_t visitor = [sid, &session_leader](sinsp_threadinfo* pt)
{
if(pt->m_sid != sid)
{
return false;
}
session_leader = pt;
return true;
};

tinfo->traverse_parent_state(visitor);

// session_leader has been updated to the highest process that has the same session id.
// session_leader's comm is considered the session leader.
m_tstr = session_leader->get_comm();
m_tstr = extract_leader_attribute_thread_hierarchy<std::string>(tinfo, [](sinsp_threadinfo* t) { return t->m_sid; }, [](sinsp_threadinfo* t) { return t->get_comm(); });
RETURN_EXTRACT_STRING(m_tstr);
}
case TYPE_SID_EXE:
{
int64_t sid = tinfo->m_sid;

if(!tinfo->is_in_pid_namespace())
{
// Relying on the convention that a session id is the process id of the session leader.
// `threadinfo` lookup only applies when the process is running on the host and not in a pid
// namespace. However, if the process is running in a pid namespace, we instead traverse the process
// lineage until we find a match.
sinsp_threadinfo* sinfo = m_inspector->get_thread_ref(sid, false, true).get();
if(sinfo != NULL)
{
m_tstr = sinfo->get_exe();
RETURN_EXTRACT_STRING(m_tstr);
}
}

// This can occur when the session leader process has exited or if the process
// is running in a pid namespace and we only have the virtual session id, as
// seen from its pid namespace.
// Find the highest ancestor process that has the same session id and
// declare it to be the session leader.
sinsp_threadinfo* session_leader = tinfo;

sinsp_threadinfo::visitor_func_t visitor = [sid, &session_leader](sinsp_threadinfo* pt)
{
if(pt->m_sid != sid)
{
return false;
}
session_leader = pt;
return true;
};

tinfo->traverse_parent_state(visitor);

// session_leader has been updated to the highest process that has the same session id.
// session_leader's exe is considered the session leader.
m_tstr = session_leader->get_exe();
m_tstr = extract_leader_attribute_thread_hierarchy<std::string>(tinfo, [](sinsp_threadinfo* t) { return t->m_sid; }, [](sinsp_threadinfo* t) { return t->get_exe(); });
RETURN_EXTRACT_STRING(m_tstr);
}
case TYPE_SID_EXEPATH:
{
int64_t sid = tinfo->m_sid;

if(!tinfo->is_in_pid_namespace())
{
// Relying on the convention that a session id is the process id of the session leader.
// `threadinfo` lookup only applies when the process is running on the host and not in a pid
// namespace. However, if the process is running in a pid namespace, we instead traverse the process
// lineage until we find a match.
sinsp_threadinfo* sinfo = m_inspector->get_thread_ref(sid, false, true).get();
if(sinfo != NULL)
{
m_tstr = sinfo->get_exepath();
RETURN_EXTRACT_STRING(m_tstr);
}
}

// This can occur when the session leader process has exited or if the process
// is running in a pid namespace and we only have the virtual session id, as
// seen from its pid namespace.
// Find the highest ancestor process that has the same session id and
// declare it to be the session leader.
sinsp_threadinfo* session_leader = tinfo;

sinsp_threadinfo::visitor_func_t visitor = [sid, &session_leader](sinsp_threadinfo* pt)
{
if(pt->m_sid != sid)
{
return false;
}
session_leader = pt;
return true;
};

tinfo->traverse_parent_state(visitor);

// session_leader has been updated to the highest process that has the same session id.
// session_leader's exepath is considered the session leader.
m_tstr = session_leader->get_exepath();
m_tstr = extract_leader_attribute_thread_hierarchy<std::string>(tinfo, [](sinsp_threadinfo* t) { return t->m_sid; }, [](sinsp_threadinfo* t) { return t->get_exepath(); });
RETURN_EXTRACT_STRING(m_tstr);
}
case TYPE_VPGID_NAME:
{
int64_t vpgid = tinfo->m_vpgid;

if(!tinfo->is_in_pid_namespace())
{
// Relying on the convention that a process group id is the process id of the process group leader.
// `threadinfo` lookup only applies when the process is running on the host and not in a pid
// namespace. However, if the process is running in a pid namespace, we instead traverse the process
// lineage until we find a match.
sinsp_threadinfo* vpgidinfo = m_inspector->get_thread_ref(vpgid, false, true).get();
if(vpgidinfo != NULL)
{
m_tstr = vpgidinfo->get_comm();
RETURN_EXTRACT_STRING(m_tstr);
}
}
// This can occur when the process group leader process has exited or if the process
// is running in a pid namespace and we only have the virtual process group id, as
// seen from its pid namespace.
// Find the highest ancestor process that has the same process group id and
// declare it to be the process group leader.
sinsp_threadinfo* group_leader = tinfo;

sinsp_threadinfo::visitor_func_t visitor = [vpgid, &group_leader](sinsp_threadinfo* pt)
{
if(pt->m_vpgid != vpgid)
{
return false;
}
group_leader = pt;
return true;
};

tinfo->traverse_parent_state(visitor);

// group_leader has been updated to the highest process that has the same process group id.
// group_leader's comm is considered the process group leader.
m_tstr = group_leader->get_comm();
m_tstr = extract_leader_attribute_thread_hierarchy<std::string>(tinfo, [](sinsp_threadinfo* t) { return t->m_vpgid; }, [](sinsp_threadinfo* t) { return t->get_comm(); });
RETURN_EXTRACT_STRING(m_tstr);
}
case TYPE_VPGID_EXE:
{
int64_t vpgid = tinfo->m_vpgid;

if(!tinfo->is_in_pid_namespace())
{
// Relying on the convention that a process group id is the process id of the process group leader.
// `threadinfo` lookup only applies when the process is running on the host and not in a pid
// namespace. However, if the process is running in a pid namespace, we instead traverse the process
// lineage until we find a match.
sinsp_threadinfo* vpgidinfo = m_inspector->get_thread_ref(vpgid, false, true).get();
if(vpgidinfo != NULL)
{
m_tstr = vpgidinfo->get_exe();
RETURN_EXTRACT_STRING(m_tstr);
}
}
// This can occur when the process group leader process has exited or if the process
// is running in a pid namespace and we only have the virtual process group id, as
// seen from its pid namespace.
// Find the highest ancestor process that has the same process group id and
// declare it to be the process group leader.
sinsp_threadinfo* group_leader = tinfo;

sinsp_threadinfo::visitor_func_t visitor = [vpgid, &group_leader](sinsp_threadinfo* pt)
{
if(pt->m_vpgid != vpgid)
{
return false;
}
group_leader = pt;
return true;
};

tinfo->traverse_parent_state(visitor);

// group_leader has been updated to the highest process that has the same process group id.
// group_leader's exe is considered the process group leader.
m_tstr = group_leader->get_exe();
m_tstr = extract_leader_attribute_thread_hierarchy<std::string>(tinfo, [](sinsp_threadinfo* t) { return t->m_vpgid; }, [](sinsp_threadinfo* t) { return t->get_exe(); });
RETURN_EXTRACT_STRING(m_tstr);

}
case TYPE_VPGID_EXEPATH:
{
int64_t vpgid = tinfo->m_vpgid;

if(!tinfo->is_in_pid_namespace())
{
// Relying on the convention that a process group id is the process id of the process group leader.
// `threadinfo` lookup only applies when the process is running on the host and not in a pid
// namespace. However, if the process is running in a pid namespace, we instead traverse the process
// lineage until we find a match.
sinsp_threadinfo* vpgidinfo = m_inspector->get_thread_ref(vpgid, false, true).get();
if(vpgidinfo != NULL)
{
m_tstr = vpgidinfo->get_exepath();
RETURN_EXTRACT_STRING(m_tstr);
}
}

// This can occur when the process group leader process has exited or if the process
// is running in a pid namespace and we only have the virtual process group id, as
// seen from its pid namespace.
// Find the highest ancestor process that has the same process group id and
// declare it to be the process group leader.
sinsp_threadinfo* group_leader = tinfo;

sinsp_threadinfo::visitor_func_t visitor = [vpgid, &group_leader](sinsp_threadinfo* pt)
{
if(pt->m_vpgid != vpgid)
{
return false;
}
group_leader = pt;
return true;
};

tinfo->traverse_parent_state(visitor);

// group_leader has been updated to the highest process that has the same process group id.
// group_leader's exepath is considered the process group leader.
m_tstr = group_leader->get_exepath();
m_tstr = extract_leader_attribute_thread_hierarchy<std::string>(tinfo, [](sinsp_threadinfo* t) { return t->m_vpgid; }, [](sinsp_threadinfo* t) { return t->get_exepath(); });
RETURN_EXTRACT_STRING(m_tstr);
}
case TYPE_TTY:
Expand Down
38 changes: 36 additions & 2 deletions userspace/libsinsp/sinsp_filtercheck_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,8 @@ class sinsp_filter_check_thread : public sinsp_filter_check
template<typename T>
std::string concat_attribute_thread_hierarchy(sinsp_threadinfo* mt, int32_t m_argid, const std::function<T(sinsp_threadinfo*)>& get_attribute_func)
{

// nullptr check of mt is done within each filtercheck prior to calling this function
static_assert(std::is_convertible<T, std::string>::value, "T must be convertible to std::string to concat parent lineage thread attributes");
static_assert(std::is_convertible<T, std::string>::value, "T must be convertible to std::string");
std::string result = get_attribute_func(mt);

for (int32_t j = 0; j < m_argid; j++)
Expand All @@ -153,6 +152,41 @@ class sinsp_filter_check_thread : public sinsp_filter_check
return result;
}

template<typename T>
std::string extract_leader_attribute_thread_hierarchy(sinsp_threadinfo* tinfo, const std::function<int64_t(sinsp_threadinfo*)>& get_thread_attribute_func, const std::function<T(sinsp_threadinfo*)>& get_attribute_func)
{
// nullptr check of tinfo is done prior to calling this function
static_assert(std::is_convertible<T, std::string>::value, "T must be convertible to std::string");
int64_t thread_attribute = get_thread_attribute_func(tinfo);

if (!tinfo->is_in_pid_namespace())
{
// `threadinfo` lookup only applies when the process is running on the host and not in a PID namespace.
sinsp_threadinfo* attribute_info = m_inspector->get_thread_ref(thread_attribute, false, true).get();
if (attribute_info != NULL)
{
return get_attribute_func(attribute_info);
}
}

// However, if the leader process has exited or if the process is running in a PID namespace, we instead
// traverse the process lineage until we find a match.
// Find the highest ancestor process that has the same id and declare it to be the leader.
sinsp_threadinfo* leader = tinfo;
sinsp_threadinfo::visitor_func_t visitor = [thread_attribute, &leader, get_thread_attribute_func](sinsp_threadinfo* pt)
{
if (get_thread_attribute_func(pt) != thread_attribute)
{
return false;
}
leader = pt;
return true;
};

tinfo->traverse_parent_state(visitor);
return get_attribute_func(leader);
}

int32_t m_argid;
std::string m_argname;
uint32_t m_tbool;
Expand Down

0 comments on commit df1a23a

Please sign in to comment.