// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) #include #include #include #include "execsnoop.h" const volatile bool ignore_failed = true; const volatile uid_t targ_uid = INVALID_UID; const volatile int max_args = DEFAULT_MAXARGS; static const struct event empty_event = {}; struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 10240); __type(key, pid_t); __type(value, struct event); } execs SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(key_size, sizeof(u32)); __uint(value_size, sizeof(u32)); } events SEC(".maps"); static __always_inline bool valid_uid(uid_t uid) { return uid != INVALID_UID; } SEC("tracepoint/syscalls/sys_enter_execve") int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx) { u64 id; pid_t pid, tgid; unsigned int ret; struct event *event; struct task_struct *task; const char **args = (const char **)(ctx->args[1]); const char *argp; uid_t uid = (u32)bpf_get_current_uid_gid(); int i; if (valid_uid(targ_uid) && targ_uid != uid) return 0; id = bpf_get_current_pid_tgid(); pid = (pid_t)id; tgid = id >> 32; if (bpf_map_update_elem(&execs, &pid, &empty_event, BPF_NOEXIST)) return 0; event = bpf_map_lookup_elem(&execs, &pid); if (!event) return 0; event->pid = tgid; event->uid = uid; task = (struct task_struct*)bpf_get_current_task(); event->ppid = (pid_t)BPF_CORE_READ(task, real_parent, tgid); event->args_count = 0; event->args_size = 0; ret = bpf_probe_read_user_str(event->args, ARGSIZE, (const char*)ctx->args[0]); if (ret <= ARGSIZE) { event->args_size += ret; } else { /* write an empty string */ event->args[0] = '\0'; event->args_size++; } event->args_count++; #pragma unroll for (i = 1; i < TOTAL_MAX_ARGS && i < max_args; i++) { bpf_probe_read_user(&argp, sizeof(argp), &args[i]); if (!argp) return 0; if (event->args_size > LAST_ARG) return 0; ret = bpf_probe_read_user_str(&event->args[event->args_size], ARGSIZE, argp); if (ret > ARGSIZE) return 0; event->args_count++; event->args_size += ret; } /* try to read one more argument to check if there is one */ bpf_probe_read_user(&argp, sizeof(argp), &args[max_args]); if (!argp) return 0; /* pointer to max_args+1 isn't null, asume we have more arguments */ event->args_count++; return 0; } SEC("tracepoint/syscalls/sys_exit_execve") int tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit* ctx) { u64 id; pid_t pid; int ret; struct event *event; u32 uid = (u32)bpf_get_current_uid_gid(); if (valid_uid(targ_uid) && targ_uid != uid) return 0; id = bpf_get_current_pid_tgid(); pid = (pid_t)id; event = bpf_map_lookup_elem(&execs, &pid); if (!event) return 0; ret = ctx->ret; if (ignore_failed && ret < 0) goto cleanup; event->retval = ret; bpf_get_current_comm(&event->comm, sizeof(event->comm)); size_t len = EVENT_SIZE(event); if (len <= sizeof(*event)) bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, event, len); cleanup: bpf_map_delete_elem(&execs, &pid); return 0; } char LICENSE[] SEC("license") = "GPL";