adbdguard/bpf/sendrecv.bpf.c
Pakin 50bd00b77b v0.1.1 testing backends (break a lot!)
- ptrace: parallel & v2 (daemon + seize)
- bpf: not working
- uprobe: not working
2025-08-29 09:17:29 +07:00

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);
}