blob: 4ea887f89d6bb1e4261a3fa5015e88f9fed149ea [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2021 Hengqi Chen
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include "statsnoop.h"
#define MAX_ENTRIES 10240
const volatile pid_t target_pid = 0;
const volatile bool trace_failed_only = false;
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_ENTRIES);
__type(key, __u32);
__type(value, const char *);
} values 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 int probe_entry(void *ctx, const char *pathname)
{
__u64 id = bpf_get_current_pid_tgid();
__u32 pid = id >> 32;
__u32 tid = (__u32)id;
if (!pathname)
return 0;
if (target_pid && target_pid != pid)
return 0;
bpf_map_update_elem(&values, &tid, &pathname, BPF_ANY);
return 0;
};
static int probe_return(void *ctx, int ret)
{
__u64 id = bpf_get_current_pid_tgid();
__u32 pid = id >> 32;
__u32 tid = (__u32)id;
const char **pathname;
struct event event = {};
pathname = bpf_map_lookup_elem(&values, &tid);
if (!pathname)
return 0;
if (trace_failed_only && ret >= 0) {
bpf_map_delete_elem(&values, &tid);
return 0;
}
event.pid = pid;
event.ts_ns = bpf_ktime_get_ns();
event.ret = ret;
bpf_get_current_comm(&event.comm, sizeof(event.comm));
bpf_probe_read_user_str(event.pathname, sizeof(event.pathname), *pathname);
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
bpf_map_delete_elem(&values, &tid);
return 0;
}
SEC("tracepoint/syscalls/sys_enter_statfs")
int handle_statfs_entry(struct trace_event_raw_sys_enter *ctx)
{
return probe_entry(ctx, (const char *)ctx->args[0]);
}
SEC("tracepoint/syscalls/sys_exit_statfs")
int handle_statfs_return(struct trace_event_raw_sys_exit *ctx)
{
return probe_return(ctx, (int)ctx->ret);
}
SEC("tracepoint/syscalls/sys_enter_newstat")
int handle_newstat_entry(struct trace_event_raw_sys_enter *ctx)
{
return probe_entry(ctx, (const char *)ctx->args[0]);
}
SEC("tracepoint/syscalls/sys_exit_newstat")
int handle_newstat_return(struct trace_event_raw_sys_exit *ctx)
{
return probe_return(ctx, (int)ctx->ret);
}
SEC("tracepoint/syscalls/sys_enter_statx")
int handle_statx_entry(struct trace_event_raw_sys_enter *ctx)
{
return probe_entry(ctx, (const char *)ctx->args[1]);
}
SEC("tracepoint/syscalls/sys_exit_statx")
int handle_statx_return(struct trace_event_raw_sys_exit *ctx)
{
return probe_return(ctx, (int)ctx->ret);
}
SEC("tracepoint/syscalls/sys_enter_newfstatat")
int handle_newfstatat_entry(struct trace_event_raw_sys_enter *ctx)
{
return probe_entry(ctx, (const char *)ctx->args[1]);
}
SEC("tracepoint/syscalls/sys_exit_newfstatat")
int handle_newfstatat_return(struct trace_event_raw_sys_exit *ctx)
{
return probe_return(ctx, (int)ctx->ret);
}
SEC("tracepoint/syscalls/sys_enter_newlstat")
int handle_newlstat_entry(struct trace_event_raw_sys_enter *ctx)
{
return probe_entry(ctx, (const char *)ctx->args[0]);
}
SEC("tracepoint/syscalls/sys_exit_newlstat")
int handle_newlstat_return(struct trace_event_raw_sys_exit *ctx)
{
return probe_return(ctx, (int)ctx->ret);
}
char LICENSE[] SEC("license") = "GPL";