Skip to content

Commit

Permalink
tracee-ebpf: add security_bpf{,_map} events (#617)
Browse files Browse the repository at this point in the history
Add the following events to tracee-ebpf:

 - security_bpf: allows bpf() syscall command to be traced.
 - security_bpf_map: called from bpf() BPF_MAP_GET_FD_BY_ID command.

The first is important for generic bpf syscall tracing while the later
is triggered whenever some process tries to get an eBPF MAP fd in order
to read or update MAP contents: an important feature for tampering
prevention.

Signed-off-by: Rafael David Tinoco <rafaeldtinoco@gmail.com>
  • Loading branch information
Rafael David Tinoco committed Jun 2, 2021
1 parent 9387554 commit d8e348d
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
6 changes: 6 additions & 0 deletions tracee-ebpf/tracee/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ const (
SecuritySocketAcceptEventID
SecuritySocketBindEventID
SecuritySbMountEventID
SecurityBPFEventID
SecurityBPFMapEventID
MaxEventID
)

Expand Down Expand Up @@ -538,6 +540,8 @@ var EventsIDToEvent = map[int32]EventConfig{
SecuritySocketAcceptEventID: {ID: SecuritySocketAcceptEventID, ID32Bit: sys32undefined, Name: "security_socket_accept", Probes: []probe{{event: "security_socket_accept", attach: kprobe, fn: "trace_security_socket_accept"}}, Sets: []string{"lsm_hooks"}},
SecuritySocketBindEventID: {ID: SecuritySocketBindEventID, ID32Bit: sys32undefined, Name: "security_socket_bind", Probes: []probe{{event: "security_socket_bind", attach: kprobe, fn: "trace_security_socket_bind"}}, Sets: []string{"lsm_hooks"}},
SecuritySbMountEventID: {ID: SecuritySbMountEventID, ID32Bit: sys32undefined, Name: "security_sb_mount", Probes: []probe{{event: "security_sb_mount", attach: kprobe, fn: "trace_security_sb_mount"}}, Sets: []string{"default", "lsm_hooks"}},
SecurityBPFEventID: {ID: SecurityBPFEventID, ID32Bit: sys32undefined, Name: "security_bpf", Probes: []probe{{event: "security_bpf", attach: kprobe, fn: "trace_security_bpf"}}, Sets: []string{"lsm_hooks"}},
SecurityBPFMapEventID: {ID: SecurityBPFMapEventID, ID32Bit: sys32undefined, Name: "security_bpf_map", Probes: []probe{{event: "security_bpf_map", attach: kprobe, fn: "trace_security_bpf_map"}}, Sets: []string{"lsm_hooks"}},
}

// EventsIDToParams is list of the parameters (name and type) used by the events
Expand Down Expand Up @@ -903,4 +907,6 @@ var EventsIDToParams = map[int32][]external.ArgMeta{
SecuritySocketAcceptEventID: {{Type: "int", Name: "sockfd"}, {Type: "struct sockaddr*", Name: "local_addr"}},
SecuritySocketBindEventID: {{Type: "int", Name: "sockfd"}, {Type: "struct sockaddr*", Name: "local_addr"}},
SecuritySbMountEventID: {{Type: "const char*", Name: "dev_name"}, {Type: "const char*", Name: "path"}, {Type: "const char*", Name: "type"}, {Type: "unsigned long", Name: "flags"}},
SecurityBPFEventID: {{Type: "int", Name: "map_cmd"}},
SecurityBPFMapEventID: {{Type: "unsigned int", Name: "map_id"}, {Type: "const char*", Name: "map_name"}},
}
70 changes: 69 additions & 1 deletion tracee-ebpf/tracee/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@
#define SECURITY_SOCKET_ACCEPT 1017
#define SECURITY_SOCKET_BIND 1018
#define SECURITY_SB_MOUNT 1019
#define MAX_EVENT_ID 1020
#define SECURITY_BPF 1020
#define SECURITY_BPF_MAP 1021
#define MAX_EVENT_ID 1022

#define CONFIG_SHOW_SYSCALL 1
#define CONFIG_EXEC_ENV 2
Expand Down Expand Up @@ -3105,6 +3107,72 @@ int BPF_KPROBE(trace_mprotect_alert)
return 0;
}

#define BPF_OBJ_NAME_LEN 16U

SEC("kprobe/security_bpf")
int BPF_KPROBE(trace_security_bpf)
{
if (!should_trace())
return 0;

buf_t *submit_p = get_buf(SUBMIT_BUF_IDX);
if (submit_p == NULL)
return 0;

set_buf_off(SUBMIT_BUF_IDX, sizeof(context_t));

context_t context = init_and_save_context(ctx, submit_p, SECURITY_BPF, 1 /*argnum*/, 0 /*ret*/);

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

/* 1st argument == map_cmd (int) */
int map_cmd = (int)PT_REGS_PARM1(ctx);

save_to_submit_buf(submit_p, (void *)&map_cmd, sizeof(int), INT_T, DEC_ARG(0, *tags));

events_perf_submit(ctx);
return 0;
};

SEC("kprobe/security_bpf_map")
int BPF_KPROBE(trace_security_bpf_map)
{
if (!should_trace())
return 0;

buf_t *submit_p = get_buf(SUBMIT_BUF_IDX);
if (submit_p == NULL)
return 0;

set_buf_off(SUBMIT_BUF_IDX, sizeof(context_t));

context_t context = init_and_save_context(ctx, submit_p, SECURITY_BPF_MAP, 0 /*argnum*/, 0 /*ret*/);

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

struct bpf_map *map;
char map_name[BPF_OBJ_NAME_LEN];

map = (struct bpf_map *)PT_REGS_PARM1(ctx);
bpf_probe_read_kernel_str(&map_name, BPF_OBJ_NAME_LEN, (void *)&map->name);

if (*map_name != '\0') {
context.argnum+=2;
save_context_to_buf(submit_p, (void*)&context);
/* 1st argument == map_id (u32) */
save_to_submit_buf(submit_p, (void *)&map->id, sizeof(int), UINT_T, DEC_ARG(0, *tags));
/* 2nd argument == map_name (const char *) */
save_str_to_buf(submit_p, (void *)&map_name, DEC_ARG(1, *tags));
events_perf_submit(ctx);
}

return 0;
}

char LICENSE[] SEC("license") = "GPL";
int KERNEL_VERSION SEC("version") = LINUX_VERSION_CODE;

1 comment on commit d8e348d

@rafaeldtinoco
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like you suggested, now.. having the map_id tied to the security_bpf_map event, we have:

$ sudo ./dist/tracee-ebpf --debug --trace event=security_bpf_map --trace comm=bpftool
TIME(s)        UID    COMM             PID     TID     RET              EVENT                ARGS
247897.036735  0      bpftool          486982  486982  0                security_bpf_map     map_id: 409, map_name: args_map
247897.037113  0      bpftool          486982  486982  0                security_bpf_map     map_id: 410, map_name: bin_args_map
247897.037322  0      bpftool          486982  486982  0                security_bpf_map     map_id: 411, map_name: bufs
247897.037531  0      bpftool          486982  486982  0                security_bpf_map     map_id: 412, map_name: bufs_off
247897.037738  0      bpftool          486982  486982  0                security_bpf_map     map_id: 413, map_name: chosen_events_m
247897.037938  0      bpftool          486982  486982  0                security_bpf_map     map_id: 414, map_name: comm_filter
247897.038141  0      bpftool          486982  486982  0                security_bpf_map     map_id: 415, map_name: config_map
247897.038350  0      bpftool          486982  486982  0                security_bpf_map     map_id: 416, map_name: events
...

We can now check the new (to be added) MAP for map_ids (populated by tracee) within the security_bpf_map() kprobe handler and have a bool variable saying if it was a tamper attempt: (map_id is mine && pid is not) && tainted = true;

It could always exist or just when the tampering was done. Something like:

$ sudo ./dist/tracee-ebpf --debug --trace event=security_bpf_map --trace comm=bpftool
TIME(s)        UID    COMM             PID     TID     RET              EVENT                ARGS
247897.036735  0      bpftool          486982  486982  0                security_bpf_map     map_id: 409, map_name: args_map, tainted: 1
247897.037113  0      bpftool          486982  486982  0                security_bpf_map     map_id: 410, map_name: bin_args_map
...

For example.

Please sign in to comment.