Skip to content

Commit

Permalink
Separate pcaps (aquasecurity#1444)
Browse files Browse the repository at this point in the history
  • Loading branch information
roikol authored Feb 28, 2022
1 parent 6385530 commit d52b575
Show file tree
Hide file tree
Showing 9 changed files with 352 additions and 145 deletions.
26 changes: 23 additions & 3 deletions cmd/tracee-ebpf/internal/flags/flags-capture.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@ Possible options:
[artifact:]mem capture memory regions that had write+execute (w+x) protection, and then changed to execute (x) only.
[artifact:]net=interface capture network traffic of the given interface. Only TCP/UDP protocols are currently supported.
dir:/path/to/dir path where tracee will save produced artifacts. the artifact will be saved into an 'out' subdirectory. (default: /tmp/tracee).
profile creates a runtime profile of program executions and their metadata for forensics use.
clear-dir clear the captured artifacts output dir before starting (default: false).
dir:/path/to/dir path where tracee will save produced artifacts. the artifact will be saved into an 'out' subdirectory. (default: /tmp/tracee).
profile creates a runtime profile of program executions and their metadata for forensics use.
clear-dir clear the captured artifacts output dir before starting (default: false).
pcap:[per-container|per-process] capture separate pcap file based on container/process context (default: none - saving one pcap for the entire host).
Examples:
--capture exec | capture executed files into the default output directory
--capture exec --capture dir:/my/dir --capture clear-dir | delete /my/dir/out and then capture executed files into it
--capture write=/usr/bin/* --capture write=/etc/* | capture files that were written into anywhere under /usr/bin/ or /etc/
--capture profile | capture executed files and create a runtime profile in the output directory
--capture net=eth0 | capture network traffic of eth0
--capture net=eth0 --capture pcap:per-container | capture network traffic of eth0, and save pcap for each container
--capture exec --output none | capture executed files into the default output directory not printing the stream of events
Use this flag multiple times to choose multiple capture options
Expand All @@ -43,6 +45,9 @@ func PrepareCapture(captureSlice []string) (tracee.CaptureConfig, error) {
outDir := "/tmp/tracee"
clearDir := false

netCapturePerContainer := false
netCapturePerProcess := false

var filterFileWrite []string
for i := range captureSlice {
cap := captureSlice[i]
Expand Down Expand Up @@ -83,6 +88,15 @@ func PrepareCapture(captureSlice []string) (tracee.CaptureConfig, error) {
if !found {
capture.NetIfaces = append(capture.NetIfaces, iface)
}
} else if strings.HasPrefix(cap, "pcap:") {
netCaptureContext := strings.TrimPrefix(cap, "pcap:")
if netCaptureContext == "per-container" {
netCapturePerContainer = true
} else if netCaptureContext == "per-process" {
netCapturePerProcess = true
} else {
return tracee.CaptureConfig{}, fmt.Errorf("invalid network capture option: %s. accepted options - pcap:per-container or pcap:per-process", netCaptureContext)
}
} else if cap == "clear-dir" {
clearDir = true
} else if strings.HasPrefix(cap, "dir:") {
Expand All @@ -104,5 +118,11 @@ func PrepareCapture(captureSlice []string) (tracee.CaptureConfig, error) {
os.RemoveAll(capture.OutputPath)
}

if netCapturePerContainer && netCapturePerProcess {
return tracee.CaptureConfig{}, fmt.Errorf("invalid capture flags: can't use both pcap:per-container and pcap:per-process capture options")
}
capture.NetPerContainer = netCapturePerContainer
capture.NetPerProcess = netCapturePerProcess

return capture, nil
}
3 changes: 3 additions & 0 deletions docs/tracee-ebpf/capture.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ CLI Option | Description
`profile` | creates a runtime profile of program executions and their metadata for forensics use.
`dir:/path/to/dir` | path where tracee will save produced artifacts. the artifact will be saved into an 'out' subdirectory. (default: /tmp/tracee).
`clear-dir` | clear the captured artifacts output dir before starting (default: false).
`pcap:per-container` | when capturing network packets, save pcap per container
`pcap:per-process` | when capturing network packets, save pcap per process

(Use this flag multiple times to choose multiple capture options)

Expand Down Expand Up @@ -56,6 +58,7 @@ Capture pcap files

```
--capture net=enp0s3
--capture net=enp0s3 --capture pcap:per-container
```

Creates a runtime profile of program executions and their metadata for forensics use. The profiles created can be compared among executions to identify if there is any difference. For example, [use it as a github action to identify if any new process was executed since the last pipeline](https://github.com/aquasecurity/tracee-action), useful for supply chain security.
Expand Down
73 changes: 49 additions & 24 deletions pkg/ebpf/c/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ Copyright (C) Aqua Security inc.
#define OPT_DEBUG_NET (1 << 5)
#define OPT_CAPTURE_MODULES (1 << 6)
#define OPT_CGROUP_V1 (1 << 7)
#define OPT_PROCESS_INFO (1 << 8)

#define FILTER_UID_ENABLED (1 << 0)
#define FILTER_UID_OUT (1 << 1)
Expand Down Expand Up @@ -404,7 +405,7 @@ typedef struct event_context {
} context_t;

typedef struct process_context {
u64 ts; // Timestamp
u64 start_time; // thread's start time
u64 cgroup_id;
u32 pid; // PID as in the userspace term
u32 tid; // TID as in the userspace term
Expand All @@ -415,6 +416,7 @@ typedef struct process_context {
u32 uid;
u32 mnt_id;
u32 pid_id;
char comm[TASK_COMM_LEN];
} process_context_t;

typedef struct args {
Expand Down Expand Up @@ -771,6 +773,11 @@ static __always_inline u32 get_task_ppid(struct task_struct *task)
return READ_KERN(parent->tgid);
}

static __always_inline u64 get_task_start_time(struct task_struct *task)
{
return READ_KERN(task->start_time);
}

static __always_inline u32 get_task_host_pid(struct task_struct *task)
{
return READ_KERN(task->pid);
Expand Down Expand Up @@ -2408,12 +2415,17 @@ int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx)
struct task_struct *parent = (struct task_struct*)ctx->args[0];
struct task_struct *child = (struct task_struct*)ctx->args[1];

u64 start_time = get_task_start_time(child);

// note: v5.4 verifier does not like using (process_context_t *) from &data->context
process_context_t process = {};
__builtin_memcpy(&process, &data.context, sizeof(process_context_t));
process.tid = get_task_ns_pid(child);
process.host_tid = get_task_host_pid(child);
bpf_map_update_elem(&process_context_map, &process.host_tid, &process, BPF_ANY);
if (data.options & OPT_PROCESS_INFO) {
process_context_t process = {};
__builtin_memcpy(&process, &data.context, sizeof(process_context_t));
process.tid = get_task_ns_pid(child);
process.host_tid = get_task_host_pid(child);
process.start_time = start_time;
bpf_map_update_elem(&process_context_map, &process.host_tid, &process, BPF_ANY);
}

int parent_pid = get_task_host_pid(parent);
int child_pid = get_task_host_pid(child);
Expand All @@ -2440,7 +2452,7 @@ int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx)
bpf_map_update_elem(&new_pids_map, &child_pid, &child_pid, BPF_ANY);
}

if (event_chosen(SCHED_PROCESS_FORK)) {
if (event_chosen(SCHED_PROCESS_FORK) || data.options & OPT_PROCESS_INFO) {
int parent_ns_pid = get_task_ns_pid(parent);
int parent_ns_tgid = get_task_ns_tgid(parent);
int child_ns_pid = get_task_ns_pid(child);
Expand All @@ -2454,6 +2466,7 @@ int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx)
save_to_submit_buf(&data, (void*)&child_ns_pid, sizeof(int), 5);
save_to_submit_buf(&data, (void*)&child_tgid, sizeof(int), 6);
save_to_submit_buf(&data, (void*)&child_ns_tgid, sizeof(int), 7);
save_to_submit_buf(&data, (void*)&start_time, sizeof(u64), 8);

events_perf_submit(&data, SCHED_PROCESS_FORK, 0);
}
Expand All @@ -2470,8 +2483,6 @@ int tracepoint__sched__sched_process_exec(struct bpf_raw_tracepoint_args *ctx)
if (!init_event_data(&data, ctx))
return 0;

process_context_t *process = (process_context_t*) &data.context;

// Perform the following checks before should_trace() so we can filter by
// newly created containers/processes. We assume that a new container/pod
// has started when a process of a newly created cgroup and mount ns
Expand All @@ -2494,7 +2505,13 @@ int tracepoint__sched__sched_process_exec(struct bpf_raw_tracepoint_args *ctx)

// We passed all filters (in should_trace()) - add this pid to traced pids set
bpf_map_update_elem(&traced_pids_map, &data.context.host_tid, &data.context.host_tid, BPF_ANY);
bpf_map_update_elem(&process_context_map, &data.context.host_tid, process, BPF_ANY);

if (data.options & OPT_PROCESS_INFO) {
process_context_t *process = bpf_map_lookup_elem(&process_context_map, &data.context.host_tid);
if (process != NULL) {
__builtin_memcpy(process->comm, data.context.comm, TASK_COMM_LEN);
}
}

struct task_struct *task = (struct task_struct *)ctx->args[0];
struct linux_binprm *bprm = (struct linux_binprm *)ctx->args[2];
Expand Down Expand Up @@ -2541,19 +2558,23 @@ int tracepoint__sched__sched_process_exec(struct bpf_raw_tracepoint_args *ctx)
// 2. fdpath - generated filename for execveat (after
// resolving dirfd)

save_str_to_buf(&data, (void *)filename, 0);
save_str_to_buf(&data, file_path, 1);
save_args_str_arr_to_buf(&data, (void *)arg_start, (void *)arg_end, argc, 2);
if (data.options & OPT_EXEC_ENV) {
save_args_str_arr_to_buf(&data, (void *)env_start, (void *)env_end, envc, 3);
if (event_chosen(SCHED_PROCESS_EXEC) || data.options & OPT_PROCESS_INFO) {
save_str_to_buf(&data, (void *)filename, 0);
save_str_to_buf(&data, file_path, 1);
save_args_str_arr_to_buf(&data, (void *)arg_start, (void *)arg_end, argc, 2);
if (data.options & OPT_EXEC_ENV) {
save_args_str_arr_to_buf(&data, (void *)env_start, (void *)env_end, envc, 3);
}
save_to_submit_buf(&data, &s_dev, sizeof(dev_t), 4);
save_to_submit_buf(&data, &inode_nr, sizeof(unsigned long), 5);
save_to_submit_buf(&data, &invoked_from_kernel, sizeof(int), 6);
save_to_submit_buf(&data, &ctime, sizeof(u64), 7);
save_to_submit_buf(&data, &stdin_type, sizeof(unsigned short), 8);

events_perf_submit(&data, SCHED_PROCESS_EXEC, 0);
}
save_to_submit_buf(&data, &s_dev, sizeof(dev_t), 4);
save_to_submit_buf(&data, &inode_nr, sizeof(unsigned long), 5);
save_to_submit_buf(&data, &invoked_from_kernel, sizeof(int), 6);
save_to_submit_buf(&data, &ctime, sizeof(u64), 7);
save_to_submit_buf(&data, &stdin_type, sizeof(unsigned short), 8);

return events_perf_submit(&data, SCHED_PROCESS_EXEC, 0);
return 0;
}

// include/trace/events/sched.h:
Expand Down Expand Up @@ -2594,10 +2615,14 @@ int tracepoint__sched__sched_process_exit(struct bpf_raw_tracepoint_args *ctx)

long exit_code = get_task_exit_code(data.task);

save_to_submit_buf(&data, (void*)&exit_code, sizeof(long), 0);
save_to_submit_buf(&data, (void*)&group_dead, sizeof(bool), 1);
if (event_chosen(SCHED_PROCESS_EXIT) || data.options & OPT_PROCESS_INFO) {
save_to_submit_buf(&data, (void*)&exit_code, sizeof(long), 0);
save_to_submit_buf(&data, (void*)&group_dead, sizeof(bool), 1);

events_perf_submit(&data, SCHED_PROCESS_EXIT, 0);
}

return events_perf_submit(&data, SCHED_PROCESS_EXIT, 0);
return 0;
}

// include/trace/events/sched.h:
Expand Down
1 change: 1 addition & 0 deletions pkg/ebpf/c/vmlinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ struct task_struct {
struct task_struct * group_leader;
struct pid * thread_pid;
struct list_head thread_group;
u64 start_time;
const struct cred * real_cred;
char comm[16];
struct files_struct * files;
Expand Down
1 change: 1 addition & 0 deletions pkg/ebpf/events_definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5697,6 +5697,7 @@ var EventsDefinitions = map[int32]EventDefinition{
{Type: "int", Name: "child_ns_tid"},
{Type: "int", Name: "child_pid"},
{Type: "int", Name: "child_ns_pid"},
{Type: "unsigned long", Name: "start_time"},
},
},
SchedProcessExecEventID: {
Expand Down
Loading

0 comments on commit d52b575

Please sign in to comment.