Skip to content
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

Added loginuid (auid) argument to execve exit events. #1189

Merged
merged 1 commit into from
Sep 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,7 @@ FILLER(proc_startupdate_3, true)
kgid_t egid;
pid_t vtid;
pid_t vpid;
kuid_t loginuid;

/*
* flags
Expand Down Expand Up @@ -1688,6 +1689,16 @@ FILLER(proc_startupdate_3, true)
* pgid
*/
res = bpf_val_to_ring_type(data, bpf_task_pgrp_vnr(task), PT_PID);
if (res != PPM_SUCCESS)
return res;

/*
* loginuid
*/
/* TODO: implement user namespace support */
res = bpf_val_to_ring_type(data, task->loginuid.val, PT_INT32);
if (res != PPM_SUCCESS)
return res;
}

return res;
Expand Down
2 changes: 1 addition & 1 deletion driver/event_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ const struct ppm_event_info g_event_info[PPM_EVENT_MAX] = {
/* PPME_PAGE_FAULT_E */ {"page_fault", EC_OTHER, EF_SKIPPARSERESET | EF_DROP_FALCO, 3, {{"addr", PT_UINT64, PF_HEX}, {"ip", PT_UINT64, PF_HEX}, {"error", PT_FLAGS32, PF_HEX, pf_flags} } },
/* PPME_PAGE_FAULT_X */ {"NA5", EC_OTHER, EF_UNUSED, 0},
/* PPME_SYSCALL_EXECVE_19_E */{"execve", EC_PROCESS, EF_MODIFIES_STATE, 1, {{"filename", PT_FSPATH, PF_NA} } },
/* PPME_SYSCALL_EXECVE_19_X */{"execve", EC_PROCESS, EF_MODIFIES_STATE, 18, {{"res", PT_ERRNO, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_UINT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"env", PT_BYTEBUF, PF_NA}, {"tty", PT_INT32, PF_DEC}, {"pgid", PT_PID, PF_DEC} } },
/* PPME_SYSCALL_EXECVE_19_X */{"execve", EC_PROCESS, EF_MODIFIES_STATE, 19, {{"res", PT_ERRNO, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_UINT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"env", PT_BYTEBUF, PF_NA}, {"tty", PT_INT32, PF_DEC}, {"pgid", PT_PID, PF_DEC}, {"loginuid", PT_INT32, PF_DEC} } },
/* PPME_SYSCALL_SETPGID_E */{"setpgid", EC_PROCESS, EF_MODIFIES_STATE, 2, {{"pid", PT_PID, PF_DEC}, {"pgid", PT_PID, PF_DEC} } },
/* PPME_SYSCALL_SETPGID_X */{"setpgid", EC_PROCESS, EF_MODIFIES_STATE, 1, {{"res", PT_PID, PF_DEC} } },
/* PPME_SYSCALL_BPF_E */{"bpf", EC_OTHER, EF_CREATES_FD, 1, {{"cmd", PT_INT64, PF_DEC} } },
Expand Down
15 changes: 15 additions & 0 deletions driver/ppm_fillers.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ along with sysdig. If not, see <http://www.gnu.org/licenses/>.
#include <linux/quota.h>
#include <linux/tty.h>
#include <linux/uaccess.h>
#include <linux/audit.h>
#ifdef CONFIG_CGROUPS
#include <linux/cgroup.h>
#endif
Expand Down Expand Up @@ -990,6 +991,20 @@ int f_proc_startupdate(struct event_filler_arguments *args)
#endif
if (unlikely(res != PPM_SUCCESS))
return res;

/*
* loginuid
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
val = from_kuid(current_user_ns(), audit_get_loginuid(current));
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
val = audit_get_loginuid(current);
#else
val = audit_get_loginuid(current->audit_context);
#endif
res = val_to_ring(args, val, 0, false, 0);
if (unlikely(res != PPM_SUCCESS))
return res;
}

return add_sentinel(args);
Expand Down
1 change: 1 addition & 0 deletions userspace/libscap/scap.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ typedef struct scap_threadinfo
scap_fdinfo* fdlist; ///< The fd table for this process
uint64_t clone_ts;
int32_t tty;
int32_t loginuid; ///< loginuid (auid)

UT_hash_handle hh; ///< makes this structure hashable
}scap_threadinfo;
Expand Down
35 changes: 35 additions & 0 deletions userspace/libscap/scap_procs.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,31 @@ int32_t scap_proc_fill_root(struct scap_threadinfo* tinfo, const char* procdirna
}
}

int32_t scap_proc_fill_loginuid(struct scap_threadinfo* tinfo, const char* procdirname)
{
uint32_t loginuid;
char loginuid_path[SCAP_MAX_PATH_SIZE];
char line[512];
snprintf(loginuid_path, sizeof(loginuid_path), "%sloginuid", procdirname);
FILE* f = fopen(loginuid_path, "r");
if(f == NULL)
{
ASSERT(false);
return SCAP_FAILURE;
}
fgets(line, sizeof(line), f);
if(sscanf(line, "%" PRId32, &loginuid) == 1)
{
tinfo->loginuid = loginuid;
return SCAP_SUCCESS;
}
else
{
ASSERT(false);
return SCAP_FAILURE;
}
}

//
// Add a process to the list by parsing its entry under /proc
//
Expand Down Expand Up @@ -747,6 +772,16 @@ static int32_t scap_proc_add_from_proc(scap_t* handle, uint32_t tid, int parentt
return SCAP_FAILURE;
}

//
// set the loginuid
//
if(SCAP_FAILURE == scap_proc_fill_loginuid(tinfo, dir_name))
{
snprintf(error, SCAP_LASTERR_SIZE, "can't fill loginuid for %s", dir_name);
free(tinfo);
return SCAP_FAILURE;
}

if(stat(dir_name, &dirstat) == 0)
{
tinfo->clone_ts = dirstat.st_ctim.tv_sec*1000000000 + dirstat.st_ctim.tv_nsec;
Expand Down
18 changes: 16 additions & 2 deletions userspace/libscap/scap_savefile.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,8 @@ int32_t scap_write_proclist_entry_bufs(scap_t *handle, scap_dumper_t *d, struct
scap_dump_write(d, &(cgroupslen), sizeof(uint16_t)) != sizeof(uint16_t) ||
scap_dump_writev(d, cgroups, cgroupscnt) != cgroupslen ||
scap_dump_write(d, &rootlen, sizeof(uint16_t)) != sizeof(uint16_t) ||
scap_dump_write(d, (char *) root, rootlen) != rootlen)
scap_dump_write(d, (char *) root, rootlen) != rootlen ||
scap_dump_write(d, &(tinfo->loginuid), sizeof(uint32_t)) != sizeof(uint32_t))
{
snprintf(handle->m_lasterr, SCAP_LASTERR_SIZE, "error writing to file (2)");
return SCAP_FAILURE;
Expand Down Expand Up @@ -459,7 +460,8 @@ static int32_t scap_write_proclist(scap_t *handle, scap_dumper_t *d)
sizeof(int64_t) + // vtid
sizeof(int64_t) + // vpid
2 + tinfo->cgroups_len +
2 + strnlen(tinfo->root, SCAP_MAX_PATH_SIZE));
2 + strnlen(tinfo->root, SCAP_MAX_PATH_SIZE) +
sizeof(int32_t)); // loginuid;

lengths[idx++] = il;
totlen += il;
Expand Down Expand Up @@ -1217,6 +1219,7 @@ static int32_t scap_read_proclist(scap_t *handle, gzFile f, uint32_t block_lengt
tinfo.clone_ts = 0;
tinfo.tty = 0;
tinfo.exepath[0] = 0;
tinfo.loginuid = -1;

//
// len
Expand Down Expand Up @@ -1665,6 +1668,17 @@ static int32_t scap_read_proclist(scap_t *handle, gzFile f, uint32_t block_lengt
// ...
// }

//
// loginuid
//
if(sub_len && (subreadsize + sizeof(int32_t)) <= sub_len)
{
readsize = gzread(f, &(tinfo.loginuid), sizeof(int32_t));
CHECK_READ_SIZE(readsize, sizeof(uint32_t));
subreadsize += readsize;
}


//
// All parsed. Add the entry to the table, or fire the notification callback
//
Expand Down
31 changes: 16 additions & 15 deletions userspace/libsinsp/filterchecks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4066,6 +4066,8 @@ const filtercheck_field_info sinsp_filter_check_user_fields[] =
{PT_CHARBUF, EPF_NONE, PF_NA, "user.name", "user name."},
{PT_CHARBUF, EPF_NONE, PF_NA, "user.homedir", "home directory of the user."},
{PT_CHARBUF, EPF_NONE, PF_NA, "user.shell", "user's shell."},
{PT_INT32, EPF_NONE, PF_ID, "user.loginuid", "audit user id (auid)."},
{PT_CHARBUF, EPF_NONE, PF_NA, "user.loginname", "audit user name (auid)."},
};

sinsp_filter_check_user::sinsp_filter_check_user()
Expand All @@ -4092,26 +4094,15 @@ uint8_t* sinsp_filter_check_user::extract(sinsp_evt *evt, OUT uint32_t* len, boo
return NULL;
}

if(m_field_id != TYPE_UID)
if(m_field_id != TYPE_UID && m_field_id != TYPE_LOGINUID && m_field_id != TYPE_LOGINNAME)
{
unordered_map<uint32_t, scap_userinfo*>::const_iterator it;

ASSERT(m_inspector != NULL);
const unordered_map<uint32_t, scap_userinfo*>* userlist = m_inspector->get_userlist();

if(tinfo->m_uid == 0xffffffff)
{
return NULL;
}

it = userlist->find(tinfo->m_uid);
if(it == userlist->end())
uinfo = m_inspector->get_user(tinfo->m_uid);
ASSERT(uinfo != NULL);
if(uinfo == NULL)
{
return NULL;
}

uinfo = it->second;
ASSERT(uinfo != NULL);
}

switch(m_field_id)
Expand All @@ -4124,6 +4115,16 @@ uint8_t* sinsp_filter_check_user::extract(sinsp_evt *evt, OUT uint32_t* len, boo
RETURN_EXTRACT_CSTR(uinfo->homedir);
case TYPE_SHELL:
RETURN_EXTRACT_CSTR(uinfo->shell);
case TYPE_LOGINUID:
RETURN_EXTRACT_VAR(tinfo->m_loginuid);
case TYPE_LOGINNAME:
ASSERT(m_inspector != NULL);
uinfo = m_inspector->get_user(tinfo->m_loginuid);
if(uinfo == NULL)
{
return NULL;
}
RETURN_EXTRACT_CSTR(uinfo->name);
default:
ASSERT(false);
break;
Expand Down
2 changes: 2 additions & 0 deletions userspace/libsinsp/filterchecks.h
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ class sinsp_filter_check_user : public sinsp_filter_check
TYPE_NAME = 1,
TYPE_HOMEDIR = 2,
TYPE_SHELL = 3,
TYPE_LOGINUID = 4,
TYPE_LOGINNAME = 5,
};

sinsp_filter_check_user();
Expand Down
11 changes: 11 additions & 0 deletions userspace/libsinsp/parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,8 @@ void sinsp_parser::parse_clone_exit(sinsp_evt *evt)

tinfo->m_tty = ptinfo->m_tty;

tinfo->m_loginuid = ptinfo->m_loginuid;

if(!(flags & PPM_CL_CLONE_THREAD))
{
tinfo->m_env = ptinfo->m_env;
Expand Down Expand Up @@ -1187,6 +1189,7 @@ void sinsp_parser::parse_clone_exit(sinsp_evt *evt)
tinfo->m_sid = ptinfo->m_sid;
tinfo->m_vpgid = ptinfo->m_vpgid;
tinfo->m_tty = ptinfo->m_tty;
tinfo->m_loginuid = ptinfo->m_loginuid;
if(!(flags & PPM_CL_CLONE_THREAD))
{
tinfo->m_env = ptinfo->m_env;
Expand Down Expand Up @@ -1748,6 +1751,14 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt)
// ...
// }

// Get the loginuid
if(evt->get_num_params() > 17)
{
parinfo = evt->get_param(18);
ASSERT(parinfo->m_len == sizeof(uint32_t));
evt->m_tinfo->m_loginuid = *(uint32_t *) parinfo->m_val;
}

//
// execve starts with a clean fd list, so we get rid of the fd list that clone
// copied from the parent
Expand Down
18 changes: 18 additions & 0 deletions userspace/libsinsp/sinsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1500,6 +1500,7 @@ threadinfo_map_t::ptr_t sinsp::get_thread_ref(int64_t tid, bool query_os_if_not_
newti->m_uid = 0xffffffff;
newti->m_gid = 0xffffffff;
newti->m_nchilds = 0;
newti->m_loginuid = 0xffffffff;
}

//
Expand Down Expand Up @@ -1720,6 +1721,23 @@ const unordered_map<uint32_t, scap_userinfo*>* sinsp::get_userlist()
return &m_userlist;
}

scap_userinfo* sinsp::get_user(uint32_t uid)
{
unordered_map<uint32_t, scap_userinfo*>::const_iterator it;
if(uid == 0xffffffff)
{
return NULL;
}

it = m_userlist.find(uid);
if(it == m_userlist.end())
{
return NULL;
}

return it->second;
}

const unordered_map<uint32_t, scap_groupinfo*>* sinsp::get_grouplist()
{
return &m_grouplist;
Expand Down
12 changes: 12 additions & 0 deletions userspace/libsinsp/sinsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,18 @@ class SINSP_PUBLIC sinsp
*/
const unordered_map<uint32_t, scap_userinfo*>* get_userlist();

/*!
\brief Lookup for user in the user table.

\return the \ref scap_userinfo object containing full user information,
if user not found, returns NULL.

\note this call works with file captures as well, because the user
table is stored in the trace files. In that case, the returned
user list is the one of the machine where the capture happened.
*/
scap_userinfo* get_user(uint32_t uid);

/*!
\brief Return the table with all the machine user groups.

Expand Down
2 changes: 2 additions & 0 deletions userspace/libsinsp/threadinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ void sinsp_threadinfo::init()
m_parent_loop_detected = false;
m_tty = 0;
m_blprogram = NULL;
m_loginuid = 0;
}

sinsp_threadinfo::~sinsp_threadinfo()
Expand Down Expand Up @@ -420,6 +421,7 @@ void sinsp_threadinfo::init(scap_threadinfo* pi)
m_vpid = pi->vpid;
m_clone_ts = pi->clone_ts;
m_tty = pi->tty;
m_loginuid = pi->loginuid;

set_cgroups(pi->cgroups, pi->cgroups_len);
m_root = pi->root;
Expand Down
1 change: 1 addition & 0 deletions userspace/libsinsp/threadinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ class SINSP_PUBLIC sinsp_threadinfo
size_t m_program_hash;
size_t m_program_hash_falco;
int32_t m_tty;
int32_t m_loginuid; ///< loginuid (auid)

//
// State for multi-event processing
Expand Down