diff --git a/pkg/ebpf/c/capture_filtering.h b/pkg/ebpf/c/capture_filtering.h index 8ab891e67640..75f70eb88e08 100644 --- a/pkg/ebpf/c/capture_filtering.h +++ b/pkg/ebpf/c/capture_filtering.h @@ -80,40 +80,40 @@ statfunc bool filter_file_type(void *ctx, io_data_t io_data, off_t start_pos) { - bool has_type_filter = false; + bool has_file_type = false; bool type_filter_match = false; - file_type_filter_t *type_filter = bpf_map_lookup_elem(filter_map, &map_idx); + file_type_t *ftype = bpf_map_lookup_elem(filter_map, &map_idx); // Filter should be always initialized - if (unlikely(type_filter == NULL)) { + if (unlikely(ftype == NULL)) { tracee_log(ctx, BPF_LOG_LVL_WARN, BPF_LOG_ID_MAP_LOOKUP_ELEM, 0); return false; } // Do check only if there is a filter - if (*type_filter != 0 && *type_filter & FILTER_FILE_TYPE_MASK) { - has_type_filter = true; + if (*ftype != 0 && *ftype & FILTER_FILE_TYPE_MASK) { + has_file_type = true; int imode_mode = get_inode_mode_from_file(file); - if (*type_filter & FILTER_PIPE_FILES) { + if (*ftype & FILTER_PIPE_FILES) { struct pipe_inode_info *pipe = get_file_pipe_info(file); if (pipe != NULL) { type_filter_match = true; goto exit; } } - if (*type_filter & FILTER_SOCKET_FILES) { + if (*ftype & FILTER_SOCKET_FILES) { if (imode_mode & S_IFSOCK) { type_filter_match = true; goto exit; } } - if (*type_filter & FILTER_NORMAL_FILES) { + if (*ftype & FILTER_NORMAL_FILES) { if (imode_mode & S_IFREG) { type_filter_match = true; goto exit; } } - if (*type_filter & FILTER_ELF_FILES) { + if (*ftype & FILTER_ELF_FILES) { file_id_t file_id = get_file_id(file); file_id.ctime = 0; if (start_pos == 0) { @@ -140,7 +140,7 @@ statfunc bool filter_file_type(void *ctx, } exit: - return (has_type_filter && !type_filter_match); + return (has_file_type && !type_filter_match); } // Return if the file does not match any given file FD filters in the filter map (so it should be @@ -150,7 +150,7 @@ statfunc bool filter_file_fd(void *ctx, void *filter_map, size_t map_idx, struct bool has_fds_filter = false; bool fds_filter_match = false; - file_type_filter_t *fds_filter = bpf_map_lookup_elem(filter_map, &map_idx); + file_type_t *fds_filter = bpf_map_lookup_elem(filter_map, &map_idx); // Filter should be always initialized if (unlikely(fds_filter == NULL)) { tracee_log(ctx, BPF_LOG_LVL_WARN, BPF_LOG_ID_MAP_LOOKUP_ELEM, 0); diff --git a/pkg/ebpf/c/common/filtering.h b/pkg/ebpf/c/common/filtering.h index 224fcdcb3250..cb04561d6f5c 100644 --- a/pkg/ebpf/c/common/filtering.h +++ b/pkg/ebpf/c/common/filtering.h @@ -52,9 +52,9 @@ statfunc u64 should_submit(u32, event_data_t *); // FUNCTIONS // get_filter_map returns the filter map for the given version and outer map -statfunc void *get_filter_map(void *outer_map, u16 pols_version) +statfunc void *get_filter_map(void *outer_map, u16 version) { - return bpf_map_lookup_elem(outer_map, &pols_version); + return bpf_map_lookup_elem(outer_map, &version); } statfunc u64 @@ -206,7 +206,7 @@ statfunc u64 compute_scopes(program_data_t *p) } // - // unversioned filters + // boolean filters (not using versioned maps) // // TODO: Create a filter map for each boolean filter (versioning it) #3805 @@ -237,14 +237,14 @@ statfunc u64 compute_scopes(program_data_t *p) } // - // versioned filters + // equality filters (using versioned maps) // - u16 pols_version = p->event->context.policies_version; + u16 version = p->event->context.policies_version; void *filter_map = NULL; if (p->config->pid_filter_enabled_scopes) { - filter_map = get_filter_map(&pid_filter_version, pols_version); + filter_map = get_filter_map(&pid_filter_version, version); u64 filter_out_scopes = p->config->pid_filter_out_scopes; u64 mask = ~p->config->pid_filter_enabled_scopes; u64 max = p->config->pid_max; @@ -258,7 +258,7 @@ statfunc u64 compute_scopes(program_data_t *p) } if (p->config->uid_filter_enabled_scopes) { - filter_map = get_filter_map(&uid_filter_version, pols_version); + filter_map = get_filter_map(&uid_filter_version, version); u64 filter_out_scopes = p->config->uid_filter_out_scopes; u64 mask = ~p->config->uid_filter_enabled_scopes; u64 max = p->config->uid_max; @@ -268,7 +268,7 @@ statfunc u64 compute_scopes(program_data_t *p) } if (p->config->mnt_ns_filter_enabled_scopes) { - filter_map = get_filter_map(&mnt_ns_filter_version, pols_version); + filter_map = get_filter_map(&mnt_ns_filter_version, version); u64 filter_out_scopes = p->config->mnt_ns_filter_out_scopes; u64 mask = ~p->config->mnt_ns_filter_enabled_scopes; u64 mnt_id = context->mnt_id; @@ -276,7 +276,7 @@ statfunc u64 compute_scopes(program_data_t *p) } if (p->config->pid_ns_filter_enabled_scopes) { - filter_map = get_filter_map(&pid_ns_filter_version, pols_version); + filter_map = get_filter_map(&pid_ns_filter_version, version); u64 filter_out_scopes = p->config->pid_ns_filter_out_scopes; u64 mask = ~p->config->pid_ns_filter_enabled_scopes; u64 pid_id = context->pid_id; @@ -284,21 +284,21 @@ statfunc u64 compute_scopes(program_data_t *p) } if (p->config->uts_ns_filter_enabled_scopes) { - filter_map = get_filter_map(&uts_ns_filter_version, pols_version); + filter_map = get_filter_map(&uts_ns_filter_version, version); u64 filter_out_scopes = p->config->uts_ns_filter_out_scopes; u64 mask = ~p->config->uts_ns_filter_enabled_scopes; res &= equality_filter_matches(filter_out_scopes, filter_map, &context->uts_name) | mask; } if (p->config->comm_filter_enabled_scopes) { - filter_map = get_filter_map(&comm_filter_version, pols_version); + filter_map = get_filter_map(&comm_filter_version, version); u64 filter_out_scopes = p->config->comm_filter_out_scopes; u64 mask = ~p->config->comm_filter_enabled_scopes; res &= equality_filter_matches(filter_out_scopes, filter_map, &context->comm) | mask; } if (p->config->cgroup_id_filter_enabled_scopes) { - filter_map = get_filter_map(&cgroup_id_filter_version, pols_version); + filter_map = get_filter_map(&cgroup_id_filter_version, version); u64 filter_out_scopes = p->config->cgroup_id_filter_out_scopes; u64 mask = ~p->config->cgroup_id_filter_enabled_scopes; u32 cgroup_id_lsb = context->cgroup_id; @@ -306,7 +306,7 @@ statfunc u64 compute_scopes(program_data_t *p) } if (p->config->proc_tree_filter_enabled_scopes) { - filter_map = get_filter_map(&process_tree_map_version, pols_version); + filter_map = get_filter_map(&process_tree_map_version, version); u64 filter_out_scopes = p->config->proc_tree_filter_out_scopes; u64 mask = ~p->config->proc_tree_filter_enabled_scopes; u32 host_pid = context->host_pid; @@ -314,7 +314,7 @@ statfunc u64 compute_scopes(program_data_t *p) } if (p->config->bin_path_filter_enabled_scopes) { - filter_map = get_filter_map(&binary_filter_version, pols_version); + filter_map = get_filter_map(&binary_filter_version, version); u64 filter_out_scopes = p->config->bin_path_filter_out_scopes; u64 mask = ~p->config->bin_path_filter_enabled_scopes; res &= binary_filter_matches(filter_out_scopes, filter_map, proc_info) | mask; @@ -348,8 +348,8 @@ statfunc u64 should_trace(program_data_t *p) statfunc u64 should_submit(u32 event_id, event_data_t *event) { - u16 pols_version = event->context.policies_version; - void *inner_events_map = bpf_map_lookup_elem(&events_map_version, &pols_version); + u16 version = event->context.policies_version; + void *inner_events_map = bpf_map_lookup_elem(&events_map_version, &version); if (inner_events_map == NULL) return 0; diff --git a/pkg/ebpf/c/maps.h b/pkg/ebpf/c/maps.h index c7be6ad24b76..bd6cc9ccb97d 100644 --- a/pkg/ebpf/c/maps.h +++ b/pkg/ebpf/c/maps.h @@ -7,72 +7,6 @@ #include -#define MAX_STACK_ADDRESSES 1024 // max amount of diff stack trace addrs to buffer -#define MAX_STACK_DEPTH 20 // max depth of each stack trace to track - -#define BPF_MAP(_name, _type, _key_type, _value_type, _max_entries) \ - struct { \ - __uint(type, _type); \ - __uint(max_entries, _max_entries); \ - __type(key, _key_type); \ - __type(value, _value_type); \ - } _name SEC(".maps"); - -#define BPF_MAP_NO_KEY(_name, _type, _value_type, _max_entries) \ - struct { \ - __uint(type, _type); \ - __uint(max_entries, _max_entries); \ - __type(value, _value_type); \ - } _name SEC(".maps"); - -#define BPF_MAP_INNER(_name, _type, _key_type, _value_type, _max_entries) \ - struct { \ - __uint(type, _type); \ - __uint(max_entries, _max_entries); \ - __type(key, _key_type); \ - __type(value, _value_type); \ - } _name SEC(".maps"); - -#define BPF_HASH_OUTER(_name, _inner_map, _max_entries) \ - struct { \ - __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); \ - __uint(max_entries, _max_entries); \ - __type(key, u16); \ - __array(values, typeof(_inner_map)); \ - } _name SEC(".maps"); - -#define BPF_HASH(_name, _key_type, _value_type, _max_entries) \ - BPF_MAP(_name, BPF_MAP_TYPE_HASH, _key_type, _value_type, _max_entries) - -#define BPF_HASH_INNER(_name, _key_type, _value_type, _max_entries) \ - BPF_MAP_INNER(_name, BPF_MAP_TYPE_HASH, _key_type, _value_type, _max_entries) - -#define BPF_LRU_HASH(_name, _key_type, _value_type, _max_entries) \ - BPF_MAP(_name, BPF_MAP_TYPE_LRU_HASH, _key_type, _value_type, _max_entries) - -#define BPF_ARRAY(_name, _value_type, _max_entries) \ - BPF_MAP(_name, BPF_MAP_TYPE_ARRAY, u32, _value_type, _max_entries) - -#define BPF_PERCPU_ARRAY(_name, _value_type, _max_entries) \ - BPF_MAP(_name, BPF_MAP_TYPE_PERCPU_ARRAY, u32, _value_type, _max_entries) - -#define BPF_PROG_ARRAY(_name, _max_entries) \ - BPF_MAP(_name, BPF_MAP_TYPE_PROG_ARRAY, u32, u32, _max_entries) - -#define BPF_PERF_OUTPUT(_name, _max_entries) \ - BPF_MAP(_name, BPF_MAP_TYPE_PERF_EVENT_ARRAY, int, __u32, _max_entries) - -#define BPF_QUEUE(_name, _value_type, _max_entries) \ - BPF_MAP_NO_KEY(_name, BPF_MAP_TYPE_QUEUE, _value_type, _max_entries) - -#define BPF_STACK(_name, _value_type, _max_entries) \ - BPF_MAP_NO_KEY(_name, BPF_MAP_TYPE_STACK, _value_type, _max_entries) - -// stack traces: the value is 1 big byte array of the stack addresses -typedef __u64 stack_trace_t[MAX_STACK_DEPTH]; -#define BPF_STACK_TRACE(_name, _max_entries) \ - BPF_MAP(_name, BPF_MAP_TYPE_STACK_TRACE, u32, stack_trace_t, _max_entries) - enum tail_call_id_e { TAIL_VFS_WRITE, @@ -92,71 +26,596 @@ enum tail_call_id_e MAX_TAIL_CALL }; -// clang-format off - -BPF_HASH(kconfig_map, u32, u32, 10240); // kernel config variables -BPF_HASH(containers_map, u32, u8, 10240); // map cgroup id to container status {EXISTED, CREATED, STARTED} -BPF_HASH(args_map, u64, args_t, 1024); // persist args between function entry and return - -// versioned maps -BPF_HASH_INNER(uid_filter, u32, eq_t, 256); // filter events by UID prototype, for specific UIDs either by == or != -BPF_HASH_OUTER(uid_filter_version, uid_filter, 64); // map of UID filters maps -BPF_HASH_INNER(pid_filter, u32, eq_t, 256); // filter events by PID prototype -BPF_HASH_OUTER(pid_filter_version, pid_filter, 64); // map of PID filters maps -BPF_HASH_INNER(mnt_ns_filter, u64, eq_t, 256); // filter events by mount namespace id prototype -BPF_HASH_OUTER(mnt_ns_filter_version, mnt_ns_filter, 64); // map of mount namespace filters maps -BPF_HASH_INNER(pid_ns_filter, u64, eq_t, 256); // filter events by pid namespace id prototype -BPF_HASH_OUTER(pid_ns_filter_version, pid_ns_filter, 64); // map of pid namespace filters maps -BPF_HASH_INNER(uts_ns_filter, string_filter_t, eq_t, 256); // filter events by uts namespace name prototype -BPF_HASH_OUTER(uts_ns_filter_version, uts_ns_filter, 64); // map of uts namespace filters maps -BPF_HASH_INNER(comm_filter, string_filter_t, eq_t, 256); // filter events by command name prototype -BPF_HASH_OUTER(comm_filter_version, comm_filter, 64); // map of command name filters maps -BPF_HASH_INNER(cgroup_id_filter, u32, eq_t, 256); // filter events by cgroup id prototype -BPF_HASH_OUTER(cgroup_id_filter_version, cgroup_id_filter, 64); // map of cgroup id filters maps -BPF_HASH_INNER(binary_filter, binary_t, eq_t, 256); // filter events by binary path and mount namespace prototype -BPF_HASH_OUTER(binary_filter_version, binary_filter, 64); // map of binary filters maps -BPF_HASH_INNER(process_tree_map, u32, eq_t, 10240); // filter events by the ancestry of the traced process -BPF_HASH_OUTER(process_tree_map_version, process_tree_map, 64); // map of process tree maps -BPF_HASH_INNER(events_map, u32, event_config_t, MAX_EVENT_ID); // map to persist event configuration data -BPF_HASH_OUTER(events_map_version, events_map, 64); // map of events maps - -BPF_HASH(sys_32_to_64_map, u32, u32, 1024); // map 32bit to 64bit syscalls -BPF_LRU_HASH(proc_info_map, u32, proc_info_t, 10240); // holds data for every process -BPF_LRU_HASH(task_info_map, u32, task_info_t, 10240); // holds data for every task -BPF_HASH(ksymbols_map, ksym_name_t, u64, 1024); // holds the addresses of some kernel symbols -BPF_ARRAY(config_map, config_entry_t, 1); // various configurations -BPF_ARRAY(file_write_path_filter, path_filter_t, 3); // filter file write captures -BPF_ARRAY(file_read_path_filter, path_filter_t, 3); // filter file read captures -BPF_ARRAY(file_type_filter, file_type_filter_t, 2); // filter file types -BPF_ARRAY(netconfig_map, netconfig_entry_t, 1); // network related configurations -BPF_ARRAY(expected_sys_call_table, syscall_table_entry_t, MAX_SYS_CALL_TABLE_SIZE); // expected addresses of sys call table -BPF_PERCPU_ARRAY(bufs, buf_t, MAX_BUFFERS); // percpu global buffer variables -BPF_PROG_ARRAY(prog_array, MAX_TAIL_CALL); // store programs for tail calls -BPF_PROG_ARRAY(prog_array_tp, MAX_TAIL_CALL); // store programs for tail calls -BPF_PROG_ARRAY(sys_enter_tails, MAX_EVENT_ID); // store syscall specific programs for tail calls from sys_enter -BPF_PROG_ARRAY(sys_exit_tails, MAX_EVENT_ID); // store syscall specific programs for tail calls from sys_exit -BPF_PROG_ARRAY(sys_enter_submit_tail, MAX_EVENT_ID); // store program for submitting syscalls from sys_enter -BPF_PROG_ARRAY(sys_exit_submit_tail, MAX_EVENT_ID); // store program for submitting syscalls from sys_exit -BPF_PROG_ARRAY(sys_enter_init_tail, MAX_EVENT_ID); // store program for performing syscall tracking logic in sys_enter -BPF_PROG_ARRAY(sys_exit_init_tail, MAX_EVENT_ID); // store program for performing syscall tracking logic in sys_exits -BPF_STACK_TRACE(stack_addresses, MAX_STACK_ADDRESSES); // store stack traces -BPF_LRU_HASH(fd_arg_path_map, u64, fd_arg_path_t, 1024); // store fds paths by timestamp -BPF_LRU_HASH(bpf_attach_map, u32, bpf_used_helpers_t, 1024); // holds bpf prog info -BPF_LRU_HASH(bpf_attach_tmp_map, u32, bpf_used_helpers_t, 1024); // temporarily hold bpf_used_helpers_t -BPF_LRU_HASH(bpf_prog_load_map, u32, void *, 1024); // store bpf prog aux pointer between bpf_check and security_bpf_prog -BPF_PERCPU_ARRAY(event_data_map, event_data_t, 1); // persist event related data -BPF_PERCPU_ARRAY(signal_data_map, controlplane_signal_t, 1); // signal scratch map -BPF_HASH(logs_count, bpf_log_t, bpf_log_count_t, 4096); // logs count -BPF_PERCPU_ARRAY(scratch_map, scratch_t, 1); // scratch space to avoid allocating stuff on the stack -BPF_LRU_HASH(file_modification_map, file_mod_key_t, int, 10240); // hold file data to decide if should submit file modification event -BPF_LRU_HASH(io_file_path_cache_map, file_id_t, path_buf_t, 5); // store cache for IO operations path -BPF_LRU_HASH(elf_files_map, file_id_t, bool, 64); // store cache for file ELF type check - -// clang-format on - -BPF_PERF_OUTPUT(logs, 1024); // logs submission -BPF_PERF_OUTPUT(events, 1024); // events submission -BPF_PERF_OUTPUT(file_writes, 1024); // file writes events submission -BPF_PERF_OUTPUT(signals, 1024); // control plane signals submissions +// kernel config variables +struct kconfig_map { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 10240); + __type(key, u32); + __type(value, u32); +} kconfig_map SEC(".maps"); + +typedef struct kconfig_map kconfig_map_t; + +// map cgroup id to container status {EXISTED, CREATED, STARTED} +struct containers_map { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 10240); + __type(key, u32); + __type(value, u8); +} containers_map SEC(".maps"); + +typedef struct containers_map containers_map_t; + +// persist args between function entry and return +struct args_map { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1024); + __type(key, u64); + __type(value, args_t); +} args_map SEC(".maps"); + +typedef struct args_map args_map_t; + +// map 32bit to 64bit syscalls +struct sys_32_to_64_map { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1024); + __type(key, u32); + __type(value, u32); +} sys_32_to_64_map SEC(".maps"); + +typedef struct sys_32_to_64_map sys_32_to_64_map_t; + +// holds data for every process +struct proc_info_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 10240); + __type(key, u32); + __type(value, proc_info_t); +} proc_info_map SEC(".maps"); + +typedef struct proc_info_map proc_info_map_t; + +// holds data for every task +struct task_info_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 10240); + __type(key, u32); + __type(value, task_info_t); +} task_info_map SEC(".maps"); + +typedef struct task_info_map task_info_map_t; + +// holds the addresses of some kernel symbols +struct ksymbols_map { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1024); + __type(key, ksym_name_t); + __type(value, u64); +} ksymbols_map SEC(".maps"); + +typedef struct ksymbols_map ksymbols_map_t; + +// various configurations +struct config_map { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, config_entry_t); +} config_map SEC(".maps"); + +typedef struct config_map config_map_t; + +// filter file write captures +struct file_write_path_filter { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 3); + __type(key, u32); + __type(value, path_filter_t); +} file_write_path_filter SEC(".maps"); + +typedef struct file_write_path_filter file_write_path_filter_t; + +// filter file read captures +struct file_read_path_filter { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 3); + __type(key, u32); + __type(value, path_filter_t); +} file_read_path_filter SEC(".maps"); + +typedef struct file_read_path_filter file_read_path_filter_t; + +// filter file types +struct file_type_filter { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 2); + __type(key, u32); + __type(value, file_type_t); +} file_type_filter SEC(".maps"); + +typedef struct file_type_filter file_type_filter_t; + +// network related configurations +struct netconfig_map { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, netconfig_entry_t); +} netconfig_map SEC(".maps"); + +typedef struct netconfig_map netconfig_map_t; + +// expected addresses of sys call table +struct expected_sys_call_table { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, MAX_SYS_CALL_TABLE_SIZE); + __type(key, u32); + __type(value, syscall_table_entry_t); +} expected_sys_call_table SEC(".maps"); + +typedef struct expected_sys_call_table expected_sys_call_table_t; + +// percpu global buffer variables +struct bufs { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(max_entries, MAX_BUFFERS); + __type(key, u32); + __type(value, buf_t); +} bufs SEC(".maps"); + +typedef struct bufs bufs_t; + +// store programs for tail calls +struct prog_array { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, MAX_TAIL_CALL); + __type(key, u32); + __type(value, u32); +} prog_array SEC(".maps"); + +typedef struct prog_array prog_array_t; + +// store programs for tail calls +struct prog_array_tp { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, MAX_TAIL_CALL); + __type(key, u32); + __type(value, u32); +} prog_array_tp SEC(".maps"); + +typedef struct prog_array_tp prog_array_tp_t; + +// store syscall specific programs for tail calls from sys_enter +struct sys_enter_tails { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, MAX_EVENT_ID); + __type(key, u32); + __type(value, u32); +} sys_enter_tails SEC(".maps"); + +typedef struct sys_enter_tails sys_enter_tails_t; + +// store syscall specific programs for tail calls from sys_exit +struct sys_exit_tails { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, MAX_EVENT_ID); + __type(key, u32); + __type(value, u32); +} sys_exit_tails SEC(".maps"); + +typedef struct sys_exit_tails sys_exit_tails_t; + +// store program for submitting syscalls from sys_enter +struct sys_enter_submit_tail { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, MAX_EVENT_ID); + __type(key, u32); + __type(value, u32); +} sys_enter_submit_tail SEC(".maps"); + +typedef struct sys_enter_submit_tail sys_enter_submit_tail_t; + +// store program for submitting syscalls from sys_exit +struct sys_exit_submit_tail { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, MAX_EVENT_ID); + __type(key, u32); + __type(value, u32); +} sys_exit_submit_tail SEC(".maps"); + +typedef struct sys_exit_submit_tail sys_exit_submit_tail_t; + +// store program for performing syscall tracking logic in sys_enter +struct sys_enter_init_tail { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, MAX_EVENT_ID); + __type(key, u32); + __type(value, u32); +} sys_enter_init_tail SEC(".maps"); + +typedef struct sys_enter_init_tail sys_enter_init_tail_t; + +// store program for performing syscall tracking logic in sys_exits +struct sys_exit_init_tail { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, MAX_EVENT_ID); + __type(key, u32); + __type(value, u32); +} sys_exit_init_tail SEC(".maps"); + +typedef struct sys_exit_init_tail sys_exit_init_tail_t; + +// store stack traces +#define MAX_STACK_ADDRESSES 1024 // max amount of diff stack trace addrs to buffer + +struct stack_addresses { + __uint(type, BPF_MAP_TYPE_STACK_TRACE); + __uint(max_entries, MAX_STACK_ADDRESSES); + __type(key, u32); + __type(value, stack_trace_t); // 1 big byte array of the stack addresses +} stack_addresses SEC(".maps"); + +typedef struct stack_addresses stack_addresses_t; + +// store fds paths by timestamp +struct fd_arg_path_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 1024); + __type(key, u64); + __type(value, fd_arg_path_t); +} fd_arg_path_map SEC(".maps"); + +typedef struct fd_arg_path_map fd_arg_path_map_t; + +// holds bpf prog info +struct bpf_attach_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 1024); + __type(key, u32); + __type(value, bpf_used_helpers_t); +} bpf_attach_map SEC(".maps"); + +typedef struct bpf_attach_map bpf_attach_map_t; + +// temporarily hold bpf_used_helpers_t +struct bpf_attach_tmp_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 1024); + __type(key, u32); + __type(value, bpf_used_helpers_t); +} bpf_attach_tmp_map SEC(".maps"); + +typedef struct bpf_attach_tmp_map bpf_attach_tmp_map_t; + +// store bpf prog aux pointer between bpf_check and security_bpf_prog +struct bpf_prog_load_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 1024); + __type(key, u32); + __type(value, void *); +} bpf_prog_load_map SEC(".maps"); + +typedef struct bpf_prog_load_map bpf_prog_load_map_t; + +// persist event related data +struct event_data_map { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, event_data_t); +} event_data_map SEC(".maps"); + +typedef struct event_data_map event_data_map_t; + +// signal scratch map +struct signal_data_map { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, controlplane_signal_t); +} signal_data_map SEC(".maps"); + +typedef struct signal_data_map signal_data_map_t; + +// logs count +struct logs_count { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 4096); + __type(key, bpf_log_t); + __type(value, bpf_log_count_t); +} logs_count SEC(".maps"); + +typedef struct logs_count logs_count_t; + +// scratch space to avoid allocating stuff on the stack +struct scratch_map { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, scratch_t); +} scratch_map SEC(".maps"); + +typedef struct scratch_map scratch_map_t; + +// hold file data to decide if should submit file modification event +struct file_modification_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 10240); + __type(key, file_mod_key_t); + __type(value, s32); +} file_modification_map SEC(".maps"); + +typedef struct file_modification_map file_modification_map_t; + +// store cache for IO operations path +struct io_file_path_cache_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 5); + __type(key, file_id_t); + __type(value, path_buf_t); +} io_file_path_cache_map SEC(".maps"); + +typedef struct io_file_path_cache_map io_file_path_cache_map_t; + +// store cache for file ELF type check +struct elf_files_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 64); + __type(key, file_id_t); + __type(value, bool); +} elf_files_map SEC(".maps"); + +typedef struct elf_files_map elf_files_map_t; + +// +// versioned maps (map of maps) +// + +#define MAX_FILTER_VERSION 64 // max amount of filter versions to track + +// filter events by UID prototype, for specific UIDs either by == or != +struct uid_filter { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __type(key, u32); + __type(value, eq_t); +} uid_filter SEC(".maps"); + +typedef struct uid_filter uid_filter_t; + +// map of UID filters maps +struct uid_filter_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, uid_filter_t); +} uid_filter_version SEC(".maps"); + +typedef struct uid_filter_version uid_filter_version_t; + +// filter events by PID +struct pid_filter { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __type(key, u32); + __type(value, eq_t); +} pid_filter SEC(".maps"); + +typedef struct pid_filter pid_filter_t; + +// map of PID filters maps +struct pid_filter_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, pid_filter_t); +} pid_filter_version SEC(".maps"); + +typedef struct pid_filter_version pid_filter_version_t; + +// filter events by mount namespace id +struct mnt_ns_filter { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __type(key, u64); + __type(value, eq_t); +} mnt_ns_filter SEC(".maps"); + +typedef struct mnt_ns_filter mnt_ns_filter_t; + +// map of mount namespace filters maps +struct mnt_ns_filter_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, mnt_ns_filter_t); +} mnt_ns_filter_version SEC(".maps"); + +typedef struct mnt_ns_filter_version mnt_ns_filter_version_t; + +// filter events by pid namespace id +struct pid_ns_filter { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __type(key, u64); + __type(value, eq_t); +} pid_ns_filter SEC(".maps"); + +typedef struct pid_ns_filter pid_ns_filter_t; + +// map of pid namespace filters maps +struct pid_ns_filter_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, pid_ns_filter_t); +} pid_ns_filter_version SEC(".maps"); + +typedef struct pid_ns_filter_version pid_ns_filter_version_t; + +// filter events by uts namespace name +struct uts_ns_filter { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __type(key, string_filter_t); + __type(value, eq_t); +} uts_ns_filter SEC(".maps"); + +typedef struct uts_ns_filter uts_ns_filter_t; + +// map of uts namespace filters maps +struct uts_ns_filter_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, uts_ns_filter_t); +} uts_ns_filter_version SEC(".maps"); + +typedef struct uts_ns_filter_version uts_ns_filter_version_t; + +// filter events by command name +struct comm_filter { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __type(key, string_filter_t); + __type(value, eq_t); +} comm_filter SEC(".maps"); + +typedef struct comm_filter comm_filter_t; + +// map of command name filters maps +struct comm_filter_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, comm_filter_t); +} comm_filter_version SEC(".maps"); + +typedef struct comm_filter_version comm_filter_version_t; + +// filter events by cgroup id +struct cgroup_id_filter { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __type(key, u32); + __type(value, eq_t); +} cgroup_id_filter SEC(".maps"); + +typedef struct cgroup_id_filter cgroup_id_filter_t; + +// map of cgroup id filters maps +struct cgroup_id_filter_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, cgroup_id_filter_t); +} cgroup_id_filter_version SEC(".maps"); + +typedef struct cgroup_id_filter_version cgroup_id_filter_version_t; + +// filter events by binary path and mount namespace +struct binary_filter { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __type(key, binary_t); + __type(value, eq_t); +} binary_filter SEC(".maps"); + +typedef struct binary_filter binary_filter_t; + +// map of binary filters maps +struct binary_filter_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, binary_filter_t); +} binary_filter_version SEC(".maps"); + +typedef struct binary_filter_version binary_filter_version_t; + +// filter events by the ancestry of the traced process +struct process_tree_map { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 10240); + __type(key, u32); + __type(value, eq_t); +} process_tree_map SEC(".maps"); + +typedef struct process_tree_map process_tree_map_t; + +// map of process tree maps +struct process_tree_map_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, process_tree_map_t); +} process_tree_map_version SEC(".maps"); + +typedef struct process_tree_map_version process_tree_map_version_t; + +// map to persist event configuration data +struct events_map { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, MAX_EVENT_ID); + __type(key, u32); + __type(value, event_config_t); +} events_map SEC(".maps"); + +typedef struct events_map events_map_t; + +// map of events maps +struct events_map_version { + __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); + __uint(max_entries, MAX_FILTER_VERSION); + __type(key, u16); + __array(values, events_map_t); +} events_map_version SEC(".maps"); + +typedef struct events_map_version events_map_version_t; + +// +// perf event maps +// + +// logs submission +struct logs { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(max_entries, 1024); + __type(key, s32); + __type(value, u32); +} logs SEC(".maps"); + +typedef struct logs logs_t; + +// events submission +struct events { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(max_entries, 1024); + __type(key, s32); + __type(value, u32); +} events SEC(".maps"); + +typedef struct events events_t; + +// file writes events submission +struct file_writes { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(max_entries, 1024); + __type(key, s32); + __type(value, u32); +} file_writes SEC(".maps"); + +typedef struct file_writes file_writes_t; + +// control plane signals submissions +struct signals { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(max_entries, 1024); + __type(key, s32); + __type(value, u32); +} signals SEC(".maps"); + +typedef struct signals signals_t; #endif /* __MAPS_H__ */ diff --git a/pkg/ebpf/c/tracee.bpf.c b/pkg/ebpf/c/tracee.bpf.c index cc145d0b69f7..b61e3f6f6988 100644 --- a/pkg/ebpf/c/tracee.bpf.c +++ b/pkg/ebpf/c/tracee.bpf.c @@ -547,12 +547,12 @@ int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx) // Update the process tree map (filter related) if the parent has an entry. if (p.config->proc_tree_filter_enabled_scopes) { - u16 pols_version = p.event->context.policies_version; + u16 version = p.event->context.policies_version; // Give the compiler a hint about the map type, otherwise libbpf will complain // about missing type information. i.e.: "can't determine value size for type". - // TODO: remove map macros and use typedef for map structs #3508. - void *inner_proc_tree_map = &process_tree_map; - inner_proc_tree_map = bpf_map_lookup_elem(&process_tree_map_version, &pols_version); + process_tree_map_t *inner_proc_tree_map = &process_tree_map; + + inner_proc_tree_map = bpf_map_lookup_elem(&process_tree_map_version, &version); if (inner_proc_tree_map != NULL) { eq_t *tgid_filtered = bpf_map_lookup_elem(inner_proc_tree_map, &parent_pid); if (tgid_filtered) { @@ -652,8 +652,23 @@ enum // Forcibly create the map in all kernels, even when not needed, due to lack of // support for kernel version awareness about map loading errors. -BPF_HASH(modules_map, u64, kernel_module_t, MAX_NUM_MODULES); -BPF_HASH(new_module_map, u64, kernel_new_mod_t, MAX_NUM_MODULES); +struct modules_map { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, MAX_NUM_MODULES); + __type(key, u64); + __type(value, kernel_module_t); +} modules_map SEC(".maps"); + +typedef struct modules_map modules_map_t; + +struct new_module_map { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, MAX_NUM_MODULES); + __type(key, u64); + __type(value, kernel_new_mod_t); +} new_module_map SEC(".maps"); + +typedef struct new_module_map new_module_map_t; // We only care for modules that got deleted or inserted between our scan and if // we detected something suspicious. Since it's a very small time frame, it's @@ -664,11 +679,23 @@ BPF_HASH(new_module_map, u64, kernel_new_mod_t, MAX_NUM_MODULES); // a map), but an attacker might start unloading modules in the background and // race with the check in order to abort reporting for hidden modules. -BPF_LRU_HASH(recent_deleted_module_map, u64, kernel_deleted_mod_t, 50); -BPF_LRU_HASH(recent_inserted_module_map, - u64, - kernel_new_mod_t, - 50); // Likewise for module insertion +struct recent_deleted_module_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 50); + __type(key, u64); + __type(value, kernel_deleted_mod_t); +} recent_deleted_module_map SEC(".maps"); + +typedef struct recent_deleted_module_map recent_deleted_module_map_t; + +struct recent_inserted_module_map { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 50); // likewise for module insertion + __type(key, u64); + __type(value, kernel_new_mod_t); +} recent_inserted_module_map SEC(".maps"); + +typedef struct recent_inserted_module_map recent_inserted_module_map_t; void __always_inline lkm_seeker_send_to_userspace(struct module *mod, u32 *flags, program_data_t *p) { @@ -799,7 +826,13 @@ statfunc bool find_modules_from_module_kset_list(program_data_t *p) return !finished_iterating; } -BPF_QUEUE(walk_mod_tree_queue, rb_node_t, MAX_NUM_MODULES); // used to walk a rb tree +struct walk_mod_tree_queue { + __uint(max_entries, MAX_NUM_MODULES); + __uint(type, BPF_MAP_TYPE_QUEUE); + __type(value, rb_node_t); +} walk_mod_tree_queue SEC(".maps"); + +typedef struct walk_mod_tree_queue walk_mod_tree_queue_t; statfunc struct latch_tree_node *__lt_from_rb(struct rb_node *node, int idx) { @@ -1356,13 +1389,13 @@ int tracepoint__sched__sched_process_free(struct bpf_raw_tracepoint_args *ctx) return 0; // remove it only from the current policies version map - u16 pols_version = cfg->policies_version; + u16 version = cfg->policies_version; // Give the compiler a hint about the map type, otherwise libbpf will complain // about missing type information. i.e.: "can't determine value size for type". - // TODO: remove map macros and use typedef for map structs #3508. - void *inner_proc_tree_map = &process_tree_map; - inner_proc_tree_map = bpf_map_lookup_elem(&process_tree_map_version, &pols_version); + process_tree_map_t *inner_proc_tree_map = &process_tree_map; + + inner_proc_tree_map = bpf_map_lookup_elem(&process_tree_map_version, &version); if (inner_proc_tree_map != NULL) bpf_map_delete_elem(inner_proc_tree_map, &tgid); } @@ -5143,8 +5176,8 @@ statfunc u64 should_submit_net_event(net_event_context_t *neteventctx, { enum event_id_e evt_id = net_packet_to_net_event(packet_type); - u16 pols_version = neteventctx->eventctx.policies_version; - void *inner_events_map = bpf_map_lookup_elem(&events_map_version, &pols_version); + u16 version = neteventctx->eventctx.policies_version; + void *inner_events_map = bpf_map_lookup_elem(&events_map_version, &version); if (inner_events_map == NULL) return 0; diff --git a/pkg/ebpf/c/types.h b/pkg/ebpf/c/types.h index 46548668e5a1..0e1ff6045edc 100644 --- a/pkg/ebpf/c/types.h +++ b/pkg/ebpf/c/types.h @@ -275,10 +275,6 @@ typedef struct string_filter { char str[MAX_STR_FILTER_SIZE]; } string_filter_t; -typedef struct binary_filter { - char str[MAX_BIN_PATH_SIZE]; -} binary_filter_t; - typedef struct ksym_name { char str[MAX_KSYM_NAME_SIZE]; } ksym_name_t; @@ -536,7 +532,9 @@ enum file_modification_op FILE_MODIFICATION_DONE, }; -// Type for values representing file types filters -typedef u32 file_type_filter_t; +#define MAX_STACK_DEPTH 20 // max depth of each stack trace to track + +typedef __u64 stack_trace_t[MAX_STACK_DEPTH]; +typedef u32 file_type_t; #endif