#include "vmlinux.h"
#include
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef int pid_t;
#include "execsnoop.h"
// Define a hash map to store events
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 10240); // Maximum number of entries in the hash map
__type(key, pid_t); // Key type: PID
__type(value, struct event); // Value type: event
} execs SEC(".maps");
// Define a perf event map
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(u32));
__uint(value_size, sizeof(u32));
} events SEC(".maps");
SEC("tracepoint/syscalls/sys_enter_execve")
int tracepoint__syscalls__sys_enter_execve(
struct trace_event_raw_sys_enter *ctx) {
static const struct event empty_event = {};
// Get current process ID and timestamp
u64 id = bpf_get_current_pid_tgid();
pid_t pid = (pid_t)id;
u64 ts = bpf_ktime_get_ns();
// Get the parent PID of the current process
struct task_struct *task = (struct task_struct *)bpf_get_current_task();
pid_t parent_pid = 0;
if (task != NULL) {
if (task->real_parent != NULL) {
parent_pid = task->real_parent->tgid;
}
}
// Insert into the hash map only if the PID doesn't exist yet
if (bpf_map_update_elem(&execs, &pid, &empty_event, BPF_NOEXIST) != 0) {
return 0;
}
struct event *event = bpf_map_lookup_elem(&execs, &pid);
if (!event) {
return 0;
}
// Update event data
event->pid = pid;
event->ppid = parent_pid;
event->args_count = 0;
event->args_size = 0;
event->start_timestamp = ts;
bpf_get_current_comm(&event->comm, sizeof(event->comm));
unsigned int ret = 0;
// Get additional arguments
event->args_count++;
#pragma unroll
for (int i = 1; i < TOTAL_MAX_ARGS; i++) {
char *argp;
bpf_probe_read_user(&argp, sizeof(argp), &((char **)(ctx->args[1]))[i]);
if (!argp) {
break; // Stop if there are no more arguments
}
if (event->args_size > LAST_ARG) {
break; // Stop if we exceed the max argument size
}
ret =
bpf_probe_read_user_str(&event->args[event->args_size], ARGSIZE, argp);
if (ret > ARGSIZE) {
break; // Stop if argument string is too large
}
event->args_count++;
event->args_size += ret;
}
// Check if there are more arguments beyond the max
char *extra_argp;
bpf_probe_read_user(&extra_argp, sizeof(extra_argp),
&((char **)(ctx->args[1]))[TOTAL_MAX_ARGS]);
if (extra_argp) {
event->args_count++; // Count extra arguments if they exist
}
return 0;
}
// Tracepoint for sys_exit_execve
SEC("tracepoint/syscalls/sys_exit_execve")
int tracepoint__syscalls__sys_exit_execve(
struct trace_event_raw_sys_exit *ctx) {
u64 id = bpf_get_current_pid_tgid();
pid_t pid = (pid_t)id;
u64 ts = bpf_ktime_get_ns();
struct event *event = bpf_map_lookup_elem(&execs, &pid);
if (!event) {
return 0;
}
// Update event data (return value and end timestamp)
event->retval = ctx->ret;
event->end_timestamp = ts;
// Get the process name (comm)
bpf_get_current_comm(&event->comm, sizeof(event->comm));
// Submit the event to the perf event map
size_t len = EVENT_SIZE(event);
if (len real_parent != NULL) {
parent_pid = task->real_parent->tgid;
}
}
Кроме того, я получаю файл дампа vmlinux.h с помощью bpftool btf /sys/kernel/btf/vmlinux в формате c > vmlinux.h, проблем быть не должно (я подумай...)
typedef unsigned int uint32_t; typedef unsigned long long uint64_t; typedef int pid_t;
#include "execsnoop.h"
// Define a hash map to store events struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 10240); // Maximum number of entries in the hash map __type(key, pid_t); // Key type: PID __type(value, struct event); // Value type: event } execs SEC(".maps");
// Get additional arguments event->args_count++; #pragma unroll for (int i = 1; i < TOTAL_MAX_ARGS; i++) { char *argp; bpf_probe_read_user(&argp, sizeof(argp), &((char **)(ctx->args[1]))[i]); if (!argp) { break; // Stop if there are no more arguments }
if (event->args_size > LAST_ARG) { break; // Stop if we exceed the max argument size }
ret = bpf_probe_read_user_str(&event->args[event->args_size], ARGSIZE, argp); if (ret > ARGSIZE) { break; // Stop if argument string is too large }
event->args_count++; event->args_size += ret; }
// Check if there are more arguments beyond the max char *extra_argp; bpf_probe_read_user(&extra_argp, sizeof(extra_argp), &((char **)(ctx->args[1]))[TOTAL_MAX_ARGS]); if (extra_argp) { event->args_count++; // Count extra arguments if they exist }
return 0; }
// Tracepoint for sys_exit_execve SEC("tracepoint/syscalls/sys_exit_execve") int tracepoint__syscalls__sys_exit_execve( struct trace_event_raw_sys_exit *ctx) { u64 id = bpf_get_current_pid_tgid(); pid_t pid = (pid_t)id; u64 ts = bpf_ktime_get_ns();