Skip to content

Commit

Permalink
tracee-ebpf: add magic_write event
Browse files Browse the repository at this point in the history
  • Loading branch information
yanivagman committed Mar 4, 2021
1 parent 0c581d0 commit 228c6d3
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 23 deletions.
3 changes: 3 additions & 0 deletions tracee-ebpf/tracee/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ const (
SchedProcessExitEventID
CommitCredsEventID
SwitchTaskNSEventID
MagicWriteEventID
MaxEventID
)

Expand Down Expand Up @@ -523,6 +524,7 @@ var EventsIDToEvent = map[int32]EventConfig{
SchedProcessExitEventID: {ID: SchedProcessExitEventID, ID32Bit: sys32undefined, Name: "sched_process_exit", Probes: []probe{{event: "sched:sched_process_exit", attach: rawTracepoint, fn: "tracepoint__sched__sched_process_exit"}}, EssentialEvent: true, Sets: []string{"default", "proc", "proc_life"}},
CommitCredsEventID: {ID: CommitCredsEventID, ID32Bit: sys32undefined, Name: "commit_creds", Probes: []probe{{event: "commit_creds", attach: kprobe, fn: "trace_commit_creds"}}, Sets: []string{}},
SwitchTaskNSEventID: {ID: SwitchTaskNSEventID, ID32Bit: sys32undefined, Name: "switch_task_ns", Probes: []probe{{event: "switch_task_namespaces", attach: kprobe, fn: "trace_switch_task_namespaces"}}, Sets: []string{}},
MagicWriteEventID: {ID: MagicWriteEventID, ID32Bit: sys32undefined, Name: "magic_write", Probes: []probe{}, Sets: []string{}},
}

// EventsIDToParams is list of the parameters (name and type) used by the events
Expand Down Expand Up @@ -881,4 +883,5 @@ var EventsIDToParams = map[int32][]external.ArgMeta{
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"}},
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"}},
}
100 changes: 77 additions & 23 deletions tracee-ebpf/tracee/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
#define MAX_STACK_ADDRESSES 1024 // Max amount of different stack trace addresses to buffer in the Map
#define MAX_STACK_DEPTH 20 // Max depth of each stack trace to track
#define MAX_STR_FILTER_SIZE 16 // Max string filter size should be bounded to the size of the compared values (comm, uts)
#define FILE_MAGIC_HDR_SIZE 16 // Number of bytes to save from a file's header (for magic_write event)
#define FILE_MAGIC_MASK 15 // Mask used to pass verifier when submitting magic_write event bytes

#define SUBMIT_BUF_IDX 0
#define STRING_BUF_IDX 1
Expand Down Expand Up @@ -137,7 +139,8 @@
#define SCHED_PROCESS_EXIT 1010
#define COMMIT_CREDS 1011
#define SWITCH_TASK_NS 1012
#define MAX_EVENT_ID 1013
#define MAGIC_WRITE 1013
#define MAX_EVENT_ID 1014

#define CONFIG_SHOW_SYSCALL 1
#define CONFIG_EXEC_ENV 2
Expand Down Expand Up @@ -2186,6 +2189,17 @@ static __always_inline int do_vfs_write_writev(struct pt_regs *ctx, u32 event_id
return 0;
}

if (!event_chosen(VFS_WRITE) && !event_chosen(VFS_WRITEV) && !event_chosen(MAGIC_WRITE)) {
bpf_tail_call(ctx, &prog_array, tail_call_id);
return 0;
}

loff_t start_pos;
void *ptr;
struct iovec *vec;
size_t count;
unsigned long vlen;

struct file *file = (struct file *) saved_args.args[0];

// Get per-cpu string buffer
Expand All @@ -2197,32 +2211,37 @@ static __always_inline int do_vfs_write_writev(struct pt_regs *ctx, u32 event_id
if (off == NULL)
return -1;

if (event_chosen(VFS_WRITE) || event_chosen(VFS_WRITEV)) {
loff_t start_pos;
size_t count;
unsigned long vlen;
buf_t *submit_p = get_buf(SUBMIT_BUF_IDX);
if (submit_p == NULL)
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));
init_and_save_context(ctx, submit_p, event_id, 5 /*argnum*/, PT_REGS_RC(ctx));
if (event_id == VFS_WRITE) {
ptr = (void*) saved_args.args[1];
count = (size_t) saved_args.args[2];
} else {
vec = (struct iovec*) saved_args.args[1];
vlen = saved_args.args[2];
}
loff_t *pos = (loff_t*) saved_args.args[3];

if (event_id == VFS_WRITE) {
count = (size_t) saved_args.args[2];
} else {
vlen = saved_args.args[2];
}
loff_t *pos = (loff_t*) saved_args.args[3];
// Extract device id, inode number, and pos (offset)
dev_t s_dev = get_dev_from_file(file);
unsigned long inode_nr = get_inode_nr_from_file(file);
bpf_probe_read(&start_pos, sizeof(off_t), pos);

// Extract device id, inode number, and pos (offset)
dev_t s_dev = get_dev_from_file(file);
unsigned long inode_nr = get_inode_nr_from_file(file);
bpf_probe_read(&start_pos, sizeof(off_t), pos);
bool char_dev = (start_pos == 0);
u32 bytes_written = PT_REGS_RC(ctx);
u32 header_bytes = FILE_MAGIC_HDR_SIZE;
if (header_bytes > bytes_written)
header_bytes = bytes_written;

// Calculate write start offset
if (start_pos != 0)
start_pos -= PT_REGS_RC(ctx);
// Calculate write start offset
if (start_pos != 0)
start_pos -= bytes_written;

if (event_chosen(VFS_WRITE) || event_chosen(VFS_WRITEV)) {
set_buf_off(SUBMIT_BUF_IDX, sizeof(context_t));
init_and_save_context(ctx, submit_p, event_id, 5 /*argnum*/, PT_REGS_RC(ctx));

u64 *tags = bpf_map_lookup_elem(&params_names_map, &event_id);
if (!tags) {
Expand All @@ -2243,6 +2262,41 @@ static __always_inline int do_vfs_write_writev(struct pt_regs *ctx, u32 event_id
events_perf_submit(ctx);
}

// magic_write event checks if the header of some file is changed
if (event_chosen(MAGIC_WRITE) && !char_dev && (start_pos == 0)) {
set_buf_off(SUBMIT_BUF_IDX, sizeof(context_t));
context_t context = init_and_save_context(ctx, submit_p, MAGIC_WRITE, 2 /*argnum*/, PT_REGS_RC(ctx));

u8 header[FILE_MAGIC_HDR_SIZE];

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

save_str_to_buf(submit_p, (void *)&string_p->buf[*off], DEC_ARG(0, *tags));

if (event_id == VFS_WRITE) {
if (header_bytes < FILE_MAGIC_HDR_SIZE)
bpf_probe_read(header, header_bytes & FILE_MAGIC_MASK, ptr);
else
bpf_probe_read(header, FILE_MAGIC_HDR_SIZE, ptr);
}
else {
struct iovec io_vec;
bpf_probe_read(&io_vec, sizeof(struct iovec), &vec[0]);
if (header_bytes < FILE_MAGIC_HDR_SIZE)
bpf_probe_read(header, header_bytes & FILE_MAGIC_MASK, io_vec.iov_base);
else
bpf_probe_read(header, FILE_MAGIC_HDR_SIZE, io_vec.iov_base);
}

save_bytes_to_buf(submit_p, header, header_bytes, DEC_ARG(1, *tags));

// Submit magic_write event
events_perf_submit(ctx);
}

bpf_tail_call(ctx, &prog_array, tail_call_id);
return 0;
}
Expand Down
5 changes: 5 additions & 0 deletions tracee-ebpf/tracee/tracee.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,11 @@ func New(cfg Config) (*Tracee, error) {
t.eventsToTrace[e] = true
}

if t.eventsToTrace[MagicWriteEventID] {
setEssential(VfsWriteEventID)
setEssential(VfsWritevEventID)
}

// Compile final list of events to trace including essential events
for id, event := range EventsIDToEvent {
// If an essential event was not requested by the user, set its map value to false
Expand Down

0 comments on commit 228c6d3

Please sign in to comment.