Skip to content

Commit

Permalink
tracee-ebpf: commit_creds: submit more credentials
Browse files Browse the repository at this point in the history
  • Loading branch information
yanivagman committed Jun 2, 2021
1 parent 6e1c370 commit 2fb9a7e
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 37 deletions.
3 changes: 2 additions & 1 deletion tracee-ebpf/tracee/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const (
alertT
bytesT
u16T
credT
)

// argTag is an enum that encodes the argument types that the BPF program may write to the shared buffer
Expand Down Expand Up @@ -894,7 +895,7 @@ var EventsIDToParams = map[int32][]external.ArgMeta{
VfsWritevEventID: {{Type: "const char*", Name: "pathname"}, {Type: "dev_t", Name: "dev"}, {Type: "unsigned long", Name: "inode"}, {Type: "unsigned long", Name: "vlen"}, {Type: "off_t", Name: "pos"}},
MemProtAlertEventID: {{Type: "alert_t", Name: "alert"}},
SchedProcessExitEventID: {},
CommitCredsEventID: {{Type: "int", Name: "old_euid"}, {Type: "int", Name: "new_euid"}, {Type: "int", Name: "old_egid"}, {Type: "int", Name: "new_egid"}, {Type: "int", Name: "old_fsuid"}, {Type: "int", Name: "new_fsuid"}, {Type: "u64", Name: "old_cap_eff"}, {Type: "u64", Name: "new_cap_eff"}},
CommitCredsEventID: {{Type: "slim_cred_t", Name: "old_cred"}, {Type: "slim_cred_t", Name: "new_cred"}, {Type: "int", Name: "syscall"}},
SwitchTaskNSEventID: {{Type: "pid_t", Name: "pid"}, {Type: "u32", Name: "new_mnt"}, {Type: "u32", Name: "new_pid"}, {Type: "u32", Name: "new_uts"}, {Type: "u32", Name: "new_ipc"}, {Type: "u32", Name: "new_net"}, {Type: "u32", Name: "new_cgroup"}},
MagicWriteEventID: {{Type: "const char*", Name: "pathname"}, {Type: "bytes", Name: "bytes"}},
SecuritySocketCreateEventID: {{Type: "int", Name: "family"}, {Type: "int", Name: "type"}, {Type: "int", Name: "protocol"}, {Type: "int", Name: "kern"}},
Expand Down
18 changes: 18 additions & 0 deletions tracee-ebpf/tracee/external/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,21 @@ func (arg *Argument) UnmarshalJSON(b []byte) error {

return nil
}

// SlimCred struct is a slim version of the kernel's cred struct
// it is used to unmarshal binary data and therefore should match (bit by bit) to the `slim_cred_t` struct in the ebpf code.
type SlimCred struct {
Uid uint32 /* real UID of the task */
Gid uint32 /* real GID of the task */
Suid uint32 /* saved UID of the task */
Sgid uint32 /* saved GID of the task */
Euid uint32 /* effective UID of the task */
Egid uint32 /* effective GID of the task */
Fsuid uint32 /* UID for VFS ops */
Fsgid uint32 /* GID for VFS ops */
CapInheritable uint64 /* caps our children can inherit */
CapPermitted uint64 /* caps we're permitted */
CapEffective uint64 /* caps we can actually use */
CapBounding uint64 /* capability bounding set */
CapAmbient uint64 /* Ambient capability set */
}
121 changes: 86 additions & 35 deletions tracee-ebpf/tracee/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
#define ALERT_T 13UL
#define BYTES_T 14UL
#define U16_T 15UL
#define CRED_T 16UL
#define TYPE_MAX 255UL

#define TAG_NONE 0UL
Expand Down Expand Up @@ -318,6 +319,23 @@ typedef struct network_connection_v6 {
u16 remote_port;
} net_conn_v6_t;

// For a good summary about capabilities, see https://lwn.net/Articles/636533/
typedef struct slim_cred {
uid_t uid; /* real UID of the task */
gid_t gid; /* real GID of the task */
uid_t suid; /* saved UID of the task */
gid_t sgid; /* saved GID of the task */
uid_t euid; /* effective UID of the task */
gid_t egid; /* effective GID of the task */
uid_t fsuid; /* UID for VFS ops */
gid_t fsgid; /* GID for VFS ops */
u64 cap_inheritable; /* caps our children can inherit */
u64 cap_permitted; /* caps we're permitted */
u64 cap_effective; /* caps we can actually use */
u64 cap_bset; /* capability bounding set */
u64 cap_ambient; /* Ambient capability set */
} slim_cred_t;

/*================================ KERNEL STRUCTS =============================*/

struct mnt_namespace {
Expand Down Expand Up @@ -2154,59 +2172,92 @@ int BPF_KPROBE(trace_commit_creds)
return 0;
set_buf_off(SUBMIT_BUF_IDX, sizeof(context_t));

u8 argnum = 0;
context_t context = init_and_save_context(ctx, submit_p, COMMIT_CREDS, 2 /*argnum*/, 0 /*ret*/);

struct cred *new = (struct cred *)PT_REGS_PARM1(ctx);

struct task_struct *task = (struct task_struct *)bpf_get_current_task();
struct cred *old = (struct cred *)READ_KERN(task->real_cred);

kuid_t old_euid = READ_KERN(old->euid);
kuid_t new_euid = READ_KERN(new->euid);
kgid_t old_egid = READ_KERN(old->egid);
kgid_t new_egid = READ_KERN(new->egid);
kuid_t old_fsuid = READ_KERN(old->fsuid);
kuid_t new_fsuid = READ_KERN(new->fsuid);
kernel_cap_t old_cap_eff = READ_KERN(old->cap_effective);
kernel_cap_t new_cap_eff = READ_KERN(new->cap_effective);
slim_cred_t old_slim = {0};
slim_cred_t new_slim = {0};

old_slim.uid = READ_KERN(old->uid.val);
old_slim.gid = READ_KERN(old->gid.val);
old_slim.suid = READ_KERN(old->suid.val);
old_slim.sgid = READ_KERN(old->sgid.val);
old_slim.euid = READ_KERN(old->euid.val);
old_slim.egid = READ_KERN(old->egid.val);
old_slim.fsuid = READ_KERN(old->fsuid.val);
old_slim.fsgid = READ_KERN(old->fsgid.val);

new_slim.uid = READ_KERN(new->uid.val);
new_slim.gid = READ_KERN(new->gid.val);
new_slim.suid = READ_KERN(new->suid.val);
new_slim.sgid = READ_KERN(new->sgid.val);
new_slim.euid = READ_KERN(new->euid.val);
new_slim.egid = READ_KERN(new->egid.val);
new_slim.fsuid = READ_KERN(new->fsuid.val);
new_slim.fsgid = READ_KERN(new->fsgid.val);

// Currently (2021), there are ~40 capabilities in the Linux kernel which are stored in a u32 array of length 2.
// This might change in the (not so near) future as more capabilities will be added.
// For now, we use u64 to store this array in one piece
u64 old_cap_eff_arr = old_cap_eff.cap[1];
old_cap_eff_arr = (old_cap_eff_arr << 32) + old_cap_eff.cap[0];
u64 new_cap_eff_arr = new_cap_eff.cap[1];
new_cap_eff_arr = (new_cap_eff_arr << 32) + new_cap_eff.cap[0];
kernel_cap_t caps;
caps = READ_KERN(old->cap_inheritable);
old_slim.cap_inheritable = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];
caps = READ_KERN(old->cap_permitted);
old_slim.cap_permitted = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];
caps = READ_KERN(old->cap_effective);
old_slim.cap_effective = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];
caps = READ_KERN(old->cap_bset);
old_slim.cap_bset = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];
caps = READ_KERN(old->cap_ambient);
old_slim.cap_ambient = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];

caps = READ_KERN(new->cap_inheritable);
new_slim.cap_inheritable = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];
caps = READ_KERN(new->cap_permitted);
new_slim.cap_permitted = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];
caps = READ_KERN(new->cap_effective);
new_slim.cap_effective = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];
caps = READ_KERN(new->cap_bset);
new_slim.cap_bset = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];
caps = READ_KERN(new->cap_ambient);
new_slim.cap_ambient = ((caps.cap[1] + 0ULL) << 32) + caps.cap[0];

u64 *tags = bpf_map_lookup_elem(&params_names_map, &context.eventid);
if (!tags) {
return -1;
}

if (old_euid.val != new_euid.val) {
argnum += save_to_submit_buf(submit_p, (void*)&old_euid.val, sizeof(int), INT_T, DEC_ARG(0, *tags));
argnum += save_to_submit_buf(submit_p, (void*)&new_euid.val, sizeof(int), INT_T, DEC_ARG(1, *tags));
}

if (old_egid.val != new_egid.val) {
argnum += save_to_submit_buf(submit_p, (void*)&old_egid.val, sizeof(int), INT_T, DEC_ARG(2, *tags));
argnum += save_to_submit_buf(submit_p, (void*)&new_egid.val, sizeof(int), INT_T, DEC_ARG(3, *tags));
}

if (old_fsuid.val != new_fsuid.val) {
argnum += save_to_submit_buf(submit_p, (void*)&old_fsuid.val, sizeof(int), INT_T, DEC_ARG(4, *tags));
argnum += save_to_submit_buf(submit_p, (void*)&new_fsuid.val, sizeof(int), INT_T, DEC_ARG(5, *tags));
}

if (old_cap_eff_arr != new_cap_eff_arr) {
argnum += save_to_submit_buf(submit_p, (void*)&old_cap_eff_arr, sizeof(unsigned long), ULONG_T, DEC_ARG(6, *tags));
argnum += save_to_submit_buf(submit_p, (void*)&new_cap_eff_arr, sizeof(unsigned long), ULONG_T, DEC_ARG(7, *tags));
}
save_to_submit_buf(submit_p, (void*)&old_slim, sizeof(slim_cred_t), CRED_T, DEC_ARG(0, *tags));
save_to_submit_buf(submit_p, (void*)&new_slim, sizeof(slim_cred_t), CRED_T, DEC_ARG(1, *tags));


if ((old_slim.uid != new_slim.uid) ||
(old_slim.gid != new_slim.gid) ||
(old_slim.suid != new_slim.suid) ||
(old_slim.sgid != new_slim.sgid) ||
(old_slim.euid != new_slim.euid) ||
(old_slim.egid != new_slim.egid) ||
(old_slim.fsuid != new_slim.fsuid) ||
(old_slim.fsgid != new_slim.fsgid) ||
(old_slim.cap_inheritable != new_slim.cap_inheritable) ||
(old_slim.cap_permitted != new_slim.cap_permitted) ||
(old_slim.cap_effective != new_slim.cap_effective) ||
(old_slim.cap_bset != new_slim.cap_bset) ||
(old_slim.cap_ambient != new_slim.cap_ambient)) {

if (get_config(CONFIG_SHOW_SYSCALL)) {
int syscall_nr = get_syscall_ev_id_from_regs();
if (syscall_nr >= 0) {
context.argnum++;
save_context_to_buf(submit_p, (void*)&context);
save_to_submit_buf(submit_p, (void*)&syscall_nr, sizeof(int), INT_T, DEC_ARG(2, *tags));
}
}

if (argnum) {
context.argnum = argnum;
save_context_to_buf(submit_p, (void*)&context);
events_perf_submit(ctx);
}

Expand Down
7 changes: 6 additions & 1 deletion tracee-ebpf/tracee/tracee.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

bpf "github.com/aquasecurity/libbpfgo"
"github.com/aquasecurity/libbpfgo/helpers"
"github.com/aquasecurity/tracee/tracee-ebpf/tracee/external"
)

// Config is a struct containing user defined configuration of tracee
Expand Down Expand Up @@ -1127,7 +1128,7 @@ func (t *Tracee) prepareArgsForPrint(ctx *context, args map[argTag]interface{})
}
}
switch ctx.EventID {
case SysEnterEventID, SysExitEventID, CapCapableEventID:
case SysEnterEventID, SysExitEventID, CapCapableEventID, CommitCredsEventID:
//show syscall name instead of id
if id, isInt32 := args[t.EncParamName[ctx.EventID%2]["syscall"]].(int32); isInt32 {
if event, isKnown := EventsIDToEvent[id]; isKnown {
Expand Down Expand Up @@ -1615,6 +1616,10 @@ func readArgFromBuff(dataBuff io.Reader) (argTag, interface{}, error) {
var data alert
err = binary.Read(dataBuff, binary.LittleEndian, &data)
res = data
case credT:
var data external.SlimCred
err = binary.Read(dataBuff, binary.LittleEndian, &data)
res = data
case strT:
res, err = readStringFromBuff(dataBuff)
case strArrT:
Expand Down

0 comments on commit 2fb9a7e

Please sign in to comment.