150 lines
4 KiB
C
150 lines
4 KiB
C
#include "vmlinux.h"
|
|
#include <asm/types.h>
|
|
|
|
#include <linux/bpf_common.h>
|
|
// #include <bpf/bpf.h>
|
|
|
|
#include <bpf/bpf_helpers.h>
|
|
|
|
// Target: arm64 calling convention
|
|
#ifndef __TARGET_ARCH_arm64
|
|
# define __TARGET_ARCH_arm64
|
|
#endif
|
|
|
|
#ifndef __PT_PARM1_REG
|
|
struct user_pt_regs {
|
|
__u64 regs[31];
|
|
__u64 sp;
|
|
__u64 pc;
|
|
__u64 pstate;
|
|
};
|
|
#define __PT_PARM1_REG regs[0]
|
|
#define __PT_PARM2_REG regs[1]
|
|
#define __PT_PARM3_REG regs[2]
|
|
#define __PT_PARM4_REG regs[3]
|
|
#define __PT_PARM5_REG regs[4]
|
|
#define __PT_PARM6_REG regs[5]
|
|
#define __PT_RC_REG regs[0]
|
|
#endif
|
|
|
|
#include <bpf/bpf_tracing.h>
|
|
#include <bpf/bpf_core_read.h>
|
|
|
|
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
|
|
|
#define MAX_PEEK 256
|
|
|
|
struct call_ctx {
|
|
uint64_t buf;
|
|
uint64_t len;
|
|
uint32_t is_send; // 1=send/write, 0=recv/read
|
|
};
|
|
|
|
struct event {
|
|
uint32_t pid, tid;
|
|
uint32_t is_send;
|
|
uint32_t len;
|
|
uint8_t data[MAX_PEEK];
|
|
};
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_HASH);
|
|
__type(key, uint32_t); // tid
|
|
__type(value, struct call_ctx);
|
|
__uint(max_entries, 8192);
|
|
} in_flight SEC(".maps");
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
|
__uint(max_entries, 1 << 22);
|
|
} rb SEC(".maps");
|
|
|
|
// helpers
|
|
static __always_inline void save_ctx(uint32_t tid, uint64_t buf, uint64_t len, uint32_t is_send) {
|
|
struct call_ctx ctx = {.buf = buf, .len = len, .is_send = is_send};
|
|
bpf_map_update_elem(&in_flight, &tid, &ctx, BPF_ANY);
|
|
}
|
|
|
|
static __always_inline int emit_ret(uint32_t tid, int64_t ret, uint32_t is_send) {
|
|
struct call_ctx *ctx = bpf_map_lookup_elem(&in_flight, &tid);
|
|
if (!ctx) return 0;
|
|
if (ret <= 0) { bpf_map_delete_elem(&in_flight, &tid); return 0; }
|
|
|
|
uint64_t want = ctx->len < (unsigned long)ret ? ctx->len : (unsigned long)ret;
|
|
if (want > MAX_PEEK) want = MAX_PEEK;
|
|
|
|
struct event *e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
|
|
if (!e) { bpf_map_delete_elem(&in_flight, &tid); return 0; }
|
|
e->pid = bpf_get_current_pid_tgid() >> 32;
|
|
e->tid = (uint32_t)bpf_get_current_pid_tgid();
|
|
e->is_send = is_send;
|
|
e->len = (uint32_t)want;
|
|
|
|
if (want > 0 && ctx->buf) {
|
|
bpf_probe_read_user(e->data, want, (void*)ctx->buf);
|
|
}
|
|
|
|
bpf_ringbuf_submit(e, 0);
|
|
bpf_map_delete_elem(&in_flight, &tid);
|
|
return 0;
|
|
}
|
|
|
|
// ---- send/write entry (x1 = buf, x2 = len)
|
|
SEC("uprobe/libc_send")
|
|
int BPF_KPROBE(up_send) {
|
|
uint32_t tid = (uint32_t)bpf_get_current_pid_tgid();
|
|
uint64_t buf = PT_REGS_PARM2(ctx);
|
|
uint64_t len = PT_REGS_PARM3(ctx);
|
|
save_ctx(tid, buf, len, 1);
|
|
return 0;
|
|
}
|
|
SEC("uretprobe/libc_send")
|
|
int BPF_KRETPROBE(ur_send) {
|
|
uint32_t tid = (uint32_t)bpf_get_current_pid_tgid();
|
|
return emit_ret(tid, PT_REGS_RC(ctx), 1);
|
|
}
|
|
|
|
// write(int fd, const void *buf, size_t count)
|
|
SEC("uprobe/libc_write")
|
|
int BPF_KPROBE(up_write) {
|
|
uint32_t tid = (uint32_t)bpf_get_current_pid_tgid();
|
|
uint64_t buf = PT_REGS_PARM2(ctx);
|
|
uint64_t len = PT_REGS_PARM3(ctx);
|
|
save_ctx(tid, buf, len, 1);
|
|
return 0;
|
|
}
|
|
SEC("uretprobe/libc_write")
|
|
int BPF_KRETPROBE(ur_write) {
|
|
uint32_t tid = (uint32_t)bpf_get_current_pid_tgid();
|
|
return emit_ret(tid, PT_REGS_RC(ctx), 1);
|
|
}
|
|
|
|
// ---- recv/read entry (x1 = buf, x2 = len)
|
|
SEC("uprobe/libc_recv")
|
|
int BPF_KPROBE(up_recv) {
|
|
uint32_t tid = (uint32_t)bpf_get_current_pid_tgid();
|
|
uint64_t buf = PT_REGS_PARM2(ctx);
|
|
uint64_t len = PT_REGS_PARM3(ctx);
|
|
save_ctx(tid, buf, len, 0);
|
|
return 0;
|
|
}
|
|
SEC("uretprobe/libc_recv")
|
|
int BPF_KRETPROBE(ur_recv) {
|
|
uint32_t tid = (uint32_t)bpf_get_current_pid_tgid();
|
|
return emit_ret(tid, PT_REGS_RC(ctx), 0);
|
|
}
|
|
|
|
// read(int fd, void *buf, size_t count)
|
|
SEC("uprobe/libc_read")
|
|
int BPF_KPROBE(up_read) {
|
|
uint32_t tid = (uint32_t)bpf_get_current_pid_tgid();
|
|
uint64_t buf = PT_REGS_PARM2(ctx);
|
|
uint64_t len = PT_REGS_PARM3(ctx);
|
|
save_ctx(tid, buf, len, 0);
|
|
return 0;
|
|
}
|
|
SEC("uretprobe/libc_read")
|
|
int BPF_KRETPROBE(ur_read) {
|
|
uint32_t tid = (uint32_t)bpf_get_current_pid_tgid();
|
|
return emit_ret(tid, PT_REGS_RC(ctx), 0);
|
|
}
|