From 15fcf6753516a1e22add87cb2b4f5de4a14540ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20I=C3=B1iguez=20Goia?= Date: Mon, 26 Feb 2024 12:44:01 +0100 Subject: [PATCH] ebpf: performance improvement for opensnitch-procs We were sending to userspace unnecessary exit events, consuming unnecessary CPU cycles. We only intercept execve and execveat, but sched_process_exit is invoked by more functions (sched_process_exit, clone, ...), so we were receiving on the daemon events that we did nothing with them, apart from consuming CPU cycles. On some scenarios like on servers running saltstack (as salt-master), this caused to consume more CPU than needed. --- ebpf_prog/opensnitch-procs.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ebpf_prog/opensnitch-procs.c b/ebpf_prog/opensnitch-procs.c index 2da48f7c5b..8603618550 100644 --- a/ebpf_prog/opensnitch-procs.c +++ b/ebpf_prog/opensnitch-procs.c @@ -46,14 +46,12 @@ static __always_inline void __handle_exit_execve(struct trace_sys_exit_execve *c { u64 pid_tgid = bpf_get_current_pid_tgid(); struct data_t *proc = bpf_map_lookup_elem(&execMap, &pid_tgid); + // don't delete the pid from execMap here, delegate it to sched_process_exit if (proc == NULL) { return; } - if (ctx->ret != 0) { goto out; } + if (ctx->ret != 0) { return; } proc->ret_code = ctx->ret; bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, proc, sizeof(*proc)); - -out: - bpf_map_delete_elem(&execMap, &pid_tgid); } // https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-4.html @@ -63,6 +61,14 @@ static __always_inline void __handle_exit_execve(struct trace_sys_exit_execve *c SEC("tracepoint/sched/sched_process_exit") int tracepoint__sched_sched_process_exit(struct pt_regs *ctx) { + u64 pid_tgid = bpf_get_current_pid_tgid(); + struct data_t *proc = bpf_map_lookup_elem(&execMap, &pid_tgid); + // if the pid is not in execMap cache (because it's not of a pid we've + // previously intercepted), do not send the event to userspace, because + // we won't do anything with it and it consumes CPU cycles (too much in some + // scenarios). + if (proc == NULL) { return 0; } + int zero = 0; struct data_t *data = bpf_map_lookup_elem(&heapstore, &zero); if (!data){ return 0; } @@ -71,7 +77,6 @@ int tracepoint__sched_sched_process_exit(struct pt_regs *ctx) data->type = EVENT_SCHED_EXIT; bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, data, sizeof(*data)); - u64 pid_tgid = bpf_get_current_pid_tgid(); bpf_map_delete_elem(&execMap, &pid_tgid); return 0; };