mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-02 23:31:08 +08:00
141 lines
3.8 KiB
C
141 lines
3.8 KiB
C
#include "../vmlinux.h"
|
|
#include <bpf/bpf_helpers.h> /* most used helpers: SEC, __always_inline, etc */
|
|
#include <bpf/bpf_core_read.h> /* for BPF CO-RE helpers */
|
|
#include <bpf/bpf_tracing.h> /* for getting kprobe arguments */
|
|
|
|
#include "../helpers.h"
|
|
|
|
#define ARGSIZE 128
|
|
#define MAXARGS 20
|
|
|
|
// Size, in bytes, of the ring buffer used to report
|
|
// audit events to userspace. This is the default,
|
|
// the userspace can adjust this value based on config.
|
|
#define EVENTS_BUF_SIZE (4096*8)
|
|
|
|
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
|
|
|
enum event_type {
|
|
EVENT_ARG,
|
|
EVENT_RET,
|
|
};
|
|
|
|
struct data_t {
|
|
// pid as in the userspace term (i.e. task->tgid in kernel).
|
|
u64 pid;
|
|
// ppid is the userspace term (i.e task->real_parent->tgid in kernel).
|
|
u64 ppid;
|
|
char comm[TASK_COMM_LEN];
|
|
enum event_type type;
|
|
char argv[ARGSIZE];
|
|
int retval;
|
|
u64 cgroup;
|
|
};
|
|
|
|
BPF_RING_BUF(execve_events, EVENTS_BUF_SIZE);
|
|
|
|
BPF_COUNTER(lost);
|
|
|
|
static int __submit_arg(void *ptr, struct data_t *data)
|
|
{
|
|
bpf_probe_read_user(data->argv, sizeof(data->argv), ptr);
|
|
if (bpf_ringbuf_output(&execve_events, data, sizeof(struct data_t), 0) != 0)
|
|
INCR_COUNTER(lost);
|
|
return 1;
|
|
}
|
|
|
|
static int submit_arg(void *ptr, struct data_t *data)
|
|
{
|
|
const char *argp = 0;
|
|
bpf_probe_read_user(&argp, sizeof(argp), ptr);
|
|
if (argp) {
|
|
return __submit_arg((void *)(argp), data);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int enter_execve(const char *filename,
|
|
const char *const *argv,
|
|
const char *const *envp)
|
|
{
|
|
// create data here and pass to submit_arg to save stack space (#555)
|
|
struct data_t data = {};
|
|
struct task_struct *task;
|
|
|
|
data.pid = bpf_get_current_pid_tgid() >> 32;
|
|
data.cgroup = bpf_get_current_cgroup_id();
|
|
|
|
task = (struct task_struct *)bpf_get_current_task();
|
|
data.ppid = BPF_CORE_READ(task, real_parent, tgid);
|
|
|
|
bpf_get_current_comm(&data.comm, sizeof(data.comm));
|
|
data.type = EVENT_ARG;
|
|
|
|
__submit_arg((void *)filename, &data);
|
|
|
|
// skip first arg, as we submitted filename
|
|
for (int i = 1; i < MAXARGS; i++) {
|
|
if (submit_arg((void *)&argv[i], &data) == 0)
|
|
goto out;
|
|
}
|
|
|
|
// handle truncated argument list
|
|
char ellipsis[] = "...";
|
|
__submit_arg((void *)ellipsis, &data);
|
|
out:
|
|
return 0;
|
|
}
|
|
|
|
static int exit_execve(int ret)
|
|
{
|
|
struct data_t data = {};
|
|
struct task_struct *task;
|
|
|
|
data.pid = bpf_get_current_pid_tgid() >> 32;
|
|
data.cgroup = bpf_get_current_cgroup_id();
|
|
|
|
task = (struct task_struct *)bpf_get_current_task();
|
|
data.ppid = BPF_CORE_READ(task, real_parent, tgid);
|
|
|
|
bpf_get_current_comm(&data.comm, sizeof(data.comm));
|
|
data.type = EVENT_RET;
|
|
data.retval = ret;
|
|
|
|
if (bpf_ringbuf_output(&execve_events, &data, sizeof(data), 0) != 0)
|
|
INCR_COUNTER(lost);
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tp/syscalls/sys_execve")
|
|
int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter *tp)
|
|
{
|
|
const char *filename = (const char *)tp->args[0];
|
|
const char *const *argv = (const char *const *)tp->args[1];
|
|
const char *const *envp = (const char *const *)tp->args[2];
|
|
|
|
return enter_execve(filename, argv, envp);
|
|
}
|
|
|
|
SEC("tp/syscalls/sys_exit_execve")
|
|
int tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit *tp)
|
|
{
|
|
return exit_execve(tp->ret);
|
|
}
|
|
|
|
SEC("tp/syscalls/sys_execveat")
|
|
int tracepoint__syscalls__sys_enter_execveat(struct trace_event_raw_sys_enter *tp)
|
|
{
|
|
const char *filename = (const char *)tp->args[1];
|
|
const char *const *argv = (const char *const *)tp->args[2];
|
|
const char *const *envp = (const char *const *)tp->args[3];
|
|
|
|
return enter_execve(filename, argv, envp);
|
|
}
|
|
|
|
SEC("tp/syscalls/sys_exit_execveat")
|
|
int tracepoint__syscalls__sys_exit_execveat(struct trace_event_raw_sys_exit *tp)
|
|
{
|
|
return exit_execve(tp->ret);
|
|
}
|