Skip to content

Commit

Permalink
libbpf-tools: add CO-RE execsnoop
Browse files Browse the repository at this point in the history
  • Loading branch information
bacher09 authored and yonghong-song committed May 21, 2020
1 parent 8c12794 commit fa8142e
Show file tree
Hide file tree
Showing 5 changed files with 497 additions and 1 deletion.
1 change: 1 addition & 0 deletions libbpf-tools/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/.output
/drsnoop
/execsnoop
/filelife
/opensnoop
/runqslower
Expand Down
2 changes: 1 addition & 1 deletion libbpf-tools/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ INCLUDES := -I$(OUTPUT)
CFLAGS := -g -O2 -Wall
ARCH := $(shell uname -m | sed 's/x86_64/x86/')

APPS = drsnoop filelife opensnoop runqslower vfsstat xfsslower
APPS = drsnoop execsnoop filelife opensnoop runqslower vfsstat xfsslower

.PHONY: all
all: $(APPS)
Expand Down
128 changes: 128 additions & 0 deletions libbpf-tools/execsnoop.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#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();

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 = pid;
event->tgid = 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_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 (int i = 1; i < TOTAL_MAX_ARGS && i < max_args; i++) {
bpf_probe_read(&argp, sizeof(argp), &args[i]);
if (!argp)
return 0;

if (event->args_size > LAST_ARG)
return 0;

ret = bpf_probe_read_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(&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";
Loading

0 comments on commit fa8142e

Please sign in to comment.