Skip to content

Commit

Permalink
fix: always initialize proc_info map
Browse files Browse the repository at this point in the history
In environments with a high amount of CPUs the current proc_info map
size of 10240 entries might not be enough, and gets filled quickly.
In these cases we got an error of missing proc_info entry.

A quick mitigation then will be to set a bigger map size.

The root cause of this issue is that we assume that if task_info exists
for some task in the task_info_map, then also the proc_info of the
process to which the task belongs to also has an entry in the map,
but that is not the case.

To fix this issue, add proc_info lookup and initialization in
init_program_data() function. In addition, init proc_info of the
relevant pid in case it was not found in other places.

Fix: #3914
  • Loading branch information
yanivagman committed Mar 14, 2024
1 parent a135237 commit 98fe549
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 53 deletions.
61 changes: 42 additions & 19 deletions pkg/ebpf/c/common/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
// PROTOTYPES

statfunc int init_context(void *, event_context_t *, struct task_struct *, u32);
statfunc task_info_t *init_task_info(u32, u32);
statfunc void init_proc_info_scratch(u32, scratch_t *);
statfunc proc_info_t *init_proc_info(u32);
statfunc void init_task_info_scratch(u32, scratch_t *);
statfunc task_info_t *init_task_info(u32);
statfunc bool context_changed(task_context_t *, task_context_t *);
statfunc int init_program_data(program_data_t *, void *);
statfunc int init_tailcall_program_data(program_data_t *, void *);
Expand Down Expand Up @@ -90,28 +93,42 @@ init_context(void *ctx, event_context_t *context, struct task_struct *task, u32
return 0;
}

statfunc task_info_t *init_task_info(u32 tid, u32 pid)
statfunc void init_proc_info_scratch(u32 pid, scratch_t *scratch)
{
int zero = 0;
__builtin_memset(&scratch->proc_info, 0, sizeof(proc_info_t));
bpf_map_update_elem(&proc_info_map, &pid, &scratch->proc_info, BPF_NOEXIST);
}

statfunc proc_info_t *init_proc_info(u32 pid)
{
u32 zero = 0;

scratch_t *scratch = bpf_map_lookup_elem(&scratch_map, &zero);
if (unlikely(scratch == NULL))
return NULL;

proc_info_t *proc_info = bpf_map_lookup_elem(&proc_info_map, &pid);
if (proc_info == NULL) {
scratch->proc_info.new_proc = false;
scratch->proc_info.follow_in_scopes = 0;
scratch->proc_info.binary.mnt_id = 0;
scratch->proc_info.binary_no_mnt = 0;
__builtin_memset(scratch->proc_info.binary.path, 0, MAX_BIN_PATH_SIZE);
bpf_map_update_elem(&proc_info_map, &pid, &scratch->proc_info, BPF_NOEXIST);
}
init_proc_info_scratch(pid, scratch);

return bpf_map_lookup_elem(&proc_info_map, &pid);
}

statfunc void init_task_info_scratch(u32 tid, scratch_t *scratch)
{
scratch->task_info.syscall_traced = false;
scratch->task_info.recompute_scope = true;
scratch->task_info.container_state = CONTAINER_UNKNOWN;
bpf_map_update_elem(&task_info_map, &tid, &scratch->task_info, BPF_NOEXIST);
}

statfunc task_info_t *init_task_info(u32 tid)
{
u32 zero = 0;

scratch_t *scratch = bpf_map_lookup_elem(&scratch_map, &zero);
if (unlikely(scratch == NULL))
return NULL;

init_task_info_scratch(tid, scratch);

return bpf_map_lookup_elem(&task_info_map, &tid);
}
Expand Down Expand Up @@ -157,15 +174,21 @@ statfunc int init_program_data(program_data_t *p, void *ctx)

bool container_lookup_required = true;

p->task_info = bpf_map_lookup_elem(&task_info_map, &p->event->context.task.host_tid);
u32 host_pid = p->event->context.task.host_pid;
p->proc_info = bpf_map_lookup_elem(&proc_info_map, &host_pid);
if (unlikely(p->proc_info == NULL)) {
p->proc_info = init_proc_info(host_pid);
if (unlikely(p->proc_info == NULL))
return 0;
}

u32 host_tid = p->event->context.task.host_tid;
p->task_info = bpf_map_lookup_elem(&task_info_map, &host_tid);
if (unlikely(p->task_info == NULL)) {
p->task_info = init_task_info(
p->event->context.task.host_tid,
p->event->context.task.host_pid
);
if (unlikely(p->task_info == NULL)) {
p->task_info = init_task_info(host_tid);
if (unlikely(p->task_info == NULL))
return 0;
}

// just initialized task info: recompute_scope is already set to true
goto out;
}
Expand Down
11 changes: 2 additions & 9 deletions pkg/ebpf/c/common/filtering.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,17 +210,10 @@ statfunc u64 compute_scopes(program_data_t *p)
task_context_t *context = &p->task_info->context;

// Don't monitor self
if (p->config->tracee_pid == context->host_pid) {
if (p->config->tracee_pid == context->host_pid)
return 0;
}

proc_info_t *proc_info = bpf_map_lookup_elem(&proc_info_map, &context->host_pid);
if (unlikely(proc_info == NULL)) {
// entry should exist in proc_map (init_program_data should have set it otherwise)
// disable logging as a workaround for instruction limit verifier error on kernel 4.19
// tracee_log(p->event->ctx, BPF_LOG_LVL_WARN, BPF_LOG_ID_MAP_LOOKUP_ELEM, 0);
return 0;
}
proc_info_t *proc_info = p->proc_info;

policies_config_t *policies_cfg = get_policies_config(p);
if (unlikely(policies_cfg == NULL)) {
Expand Down
39 changes: 14 additions & 25 deletions pkg/ebpf/c/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,9 @@ int sys_enter_init(struct bpf_raw_tracepoint_args *ctx)
u32 tid = pid_tgid;
task_info_t *task_info = bpf_map_lookup_elem(&task_info_map, &tid);
if (unlikely(task_info == NULL)) {
u32 pid = pid_tgid >> 32;
task_info = init_task_info(tid, pid);
if (unlikely(task_info == NULL)) {
task_info = init_task_info(tid);
if (unlikely(task_info == NULL))
return 0;
}
}

syscall_data_t *sys = &(task_info->syscall_data);
Expand Down Expand Up @@ -209,11 +207,9 @@ int sys_exit_init(struct bpf_raw_tracepoint_args *ctx)
u32 tid = pid_tgid;
task_info_t *task_info = bpf_map_lookup_elem(&task_info_map, &tid);
if (unlikely(task_info == NULL)) {
u32 pid = pid_tgid >> 32;
task_info = init_task_info(tid, pid);
if (unlikely(task_info == NULL)) {
task_info = init_task_info(tid);
if (unlikely(task_info == NULL))
return 0;
}
}

// check if syscall is being traced and mark that it finished
Expand Down Expand Up @@ -532,7 +528,7 @@ int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx)
return 0;
}

// Copy the parent's proc_info to the child's enty.
// Copy the parent's proc_info to the child's entry.
bpf_map_update_elem(&proc_info_map, &child_pid, p_proc_info, BPF_NOEXIST);
c_proc_info = bpf_map_lookup_elem(&proc_info_map, &child_pid);
if (unlikely(c_proc_info == NULL)) {
Expand Down Expand Up @@ -1226,14 +1222,7 @@ int tracepoint__sched__sched_process_exec(struct bpf_raw_tracepoint_args *ctx)
struct file *file = get_file_ptr_from_bprm(bprm);
void *file_path = get_path_str(__builtin_preserve_access_index(&file->f_path));

// Pick data about the process from proc_info_map
proc_info_t *proc_info = bpf_map_lookup_elem(&proc_info_map, &p.event->context.task.host_pid);
if (proc_info == NULL) {
// init_program_data should have created an entry in proc_info_map for this pid
tracee_log(ctx, BPF_LOG_LVL_WARN, BPF_LOG_ID_MAP_LOOKUP_ELEM, 0);
return 0;
}

proc_info_t *proc_info = p.proc_info;
proc_info->new_proc = true; // task has started after tracee started running

// Extract the binary name to be used in should_trace
Expand Down Expand Up @@ -4487,12 +4476,7 @@ int BPF_KPROBE(trace_load_elf_phdrs)
if (!should_trace((&p)))
return 0;

proc_info_t *proc_info = bpf_map_lookup_elem(&proc_info_map, &p.event->context.task.host_pid);
if (unlikely(proc_info == NULL)) {
// entry should exist in proc_map (init_program_data should have set it otherwise)
tracee_log(ctx, BPF_LOG_LVL_WARN, BPF_LOG_ID_MAP_LOOKUP_ELEM, 0);
return 0;
}
proc_info_t *proc_info = p.proc_info;

struct file *loaded_elf = (struct file *) PT_REGS_PARM2(ctx);
const char *elf_pathname = (char *) get_path_str(__builtin_preserve_access_index(&loaded_elf->f_path));
Expand Down Expand Up @@ -6705,8 +6689,13 @@ int sched_process_exec_signal(struct bpf_raw_tracepoint_args *ctx)
// Pick the interpreter path from the proc_info map, which is set by the "load_elf_phdrs".
u32 host_pid = get_task_host_tgid(task);
proc_info_t *proc_info = bpf_map_lookup_elem(&proc_info_map, &host_pid);
if (proc_info == NULL)
return 0;
if (proc_info == NULL) {
proc_info = init_proc_info(host_pid);
if (unlikely(proc_info == NULL)) {
tracee_log(ctx, BPF_LOG_LVL_WARN, BPF_LOG_ID_MAP_LOOKUP_ELEM, 0);
return 0;
}
}

struct file *file = get_file_ptr_from_bprm(bprm);
void *file_path = get_path_str(__builtin_preserve_access_index(&file->f_path));
Expand Down
1 change: 1 addition & 0 deletions pkg/ebpf/c/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ typedef union scratch {
typedef struct program_data {
config_entry_t *config;
task_info_t *task_info;
proc_info_t *proc_info;
event_data_t *event;
void *ctx;
} program_data_t;
Expand Down

0 comments on commit 98fe549

Please sign in to comment.