mirror of
https://github.com/springzfx/cgproxy.git
synced 2026-01-07 13:07:56 +08:00
add execsnoop-kernel which need to be built in kernel tree
This commit is contained in:
3
execsnoop-bcc/readme.md
Normal file
3
execsnoop-bcc/readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
- depend [bcc](https://github.com/iovisor/bcc)
|
||||
|
||||
- huge memory usage, at least 50M
|
||||
BIN
execsnoop-kernel/execsnoop
Executable file
BIN
execsnoop-kernel/execsnoop
Executable file
Binary file not shown.
93
execsnoop-kernel/execsnoop_kern.c
Normal file
93
execsnoop-kernel/execsnoop_kern.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "linux/sched.h"
|
||||
#include <linux/version.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
#define TASK_COMM_LEN 16
|
||||
struct event {
|
||||
char comm[TASK_COMM_LEN];
|
||||
pid_t pid;
|
||||
pid_t tgid;
|
||||
pid_t ppid;
|
||||
uid_t uid;
|
||||
};
|
||||
|
||||
/* /sys/kernel/debug/tracing/events/syscalls/sys_enter_execve/format */
|
||||
struct syscalls_enter_execve_args {
|
||||
__u64 unused;
|
||||
int syscall_nr;
|
||||
const char filename_ptr;
|
||||
const char *const * argv;
|
||||
const char *const * envp;
|
||||
};
|
||||
|
||||
/* /sys/kernel/debug/tracing/events/syscalls/sys_exit_execve/format */
|
||||
struct syscalls_exit_execve_args {
|
||||
__u64 unused;
|
||||
int syscall_nr;
|
||||
long ret;
|
||||
};
|
||||
|
||||
struct bpf_map_def SEC("maps") records = {
|
||||
.type = BPF_MAP_TYPE_HASH,
|
||||
.key_size = sizeof(pid_t),
|
||||
.value_size = sizeof(struct event),
|
||||
.max_entries = 1024,
|
||||
};
|
||||
struct bpf_map_def SEC("maps") perf_events = {
|
||||
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
|
||||
.key_size = sizeof(u32),
|
||||
.value_size = sizeof(u32),
|
||||
.max_entries = 128,
|
||||
};
|
||||
|
||||
SEC("tracepoint/syscalls/sys_enter_execve")
|
||||
int syscall_enter_execve(struct syscalls_enter_execve_args *ctx){
|
||||
pid_t pid, tgid; uid_t uid;
|
||||
struct event *event;
|
||||
struct task_struct *task, *task_p;
|
||||
|
||||
u64 id = bpf_get_current_pid_tgid();
|
||||
pid = (pid_t)id;
|
||||
tgid = id >> 32;
|
||||
uid = (__u32)bpf_get_current_uid_gid();
|
||||
|
||||
struct event empty_event={};
|
||||
if (bpf_map_update_elem(&records, &pid, &empty_event, BPF_NOEXIST)!=0) return 0;
|
||||
event = bpf_map_lookup_elem(&records, &pid);
|
||||
if (!event) return 0;
|
||||
|
||||
event->pid = pid;
|
||||
event->tgid = tgid;
|
||||
event->uid = uid;
|
||||
|
||||
/* ppid is not reliable here, normal in arch, but become 0 in ubuntu 20.04 */
|
||||
task = (struct task_struct*)bpf_get_current_task();
|
||||
bpf_probe_read(&task_p, sizeof(struct task_struct*),&task->real_parent);
|
||||
bpf_probe_read(&event->ppid,sizeof(pid_t),&task_p->tgid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("tracepoint/syscalls/sys_exit_execve")
|
||||
int syscall_exit_execve(struct syscalls_exit_execve_args *ctx){
|
||||
pid_t pid;
|
||||
struct event *event;
|
||||
|
||||
pid = (pid_t)bpf_get_current_pid_tgid();
|
||||
event = bpf_map_lookup_elem(&records,&pid);
|
||||
if (!event) return 0;
|
||||
if (ctx->ret < 0) goto cleanup;
|
||||
|
||||
/* get comm */
|
||||
bpf_get_current_comm(&event->comm,sizeof(event->comm));
|
||||
bpf_perf_event_output(ctx, &perf_events, BPF_F_CURRENT_CPU, event, sizeof(struct event));
|
||||
cleanup:
|
||||
bpf_map_delete_elem(&records, &pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
u32 _version SEC("version") = LINUX_VERSION_CODE;
|
||||
BIN
execsnoop-kernel/execsnoop_kern.o
Normal file
BIN
execsnoop-kernel/execsnoop_kern.o
Normal file
Binary file not shown.
40
execsnoop-kernel/execsnoop_user.c
Normal file
40
execsnoop-kernel/execsnoop_user.c
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
#include <signal.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include "bpf_load.h"
|
||||
|
||||
#define TASK_COMM_LEN 16
|
||||
struct event {
|
||||
char comm[TASK_COMM_LEN];
|
||||
pid_t pid;
|
||||
pid_t tgid;
|
||||
pid_t ppid;
|
||||
uid_t uid;
|
||||
};
|
||||
static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size) {
|
||||
struct event *e=data;
|
||||
printf("comm: %s, pid: %d, tgid: %d, ppid: %d, uid: %d\n",e->comm,e->pid,e->tgid,e->ppid,e->uid);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct perf_buffer_opts pb_opts = {};
|
||||
struct perf_buffer *pb;
|
||||
int ret;
|
||||
|
||||
if (load_bpf_file("execsnoop_kern.o")!=0) {
|
||||
printf("%s", bpf_log_buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pb_opts.sample_cb = print_bpf_output;
|
||||
pb = perf_buffer__new(map_fd[1], 8, &pb_opts);
|
||||
ret = libbpf_get_error(pb);
|
||||
if (ret) {
|
||||
printf("failed to setup perf_buffer: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((ret = perf_buffer__poll(pb, -1)) >= 0) {}
|
||||
kill(0, SIGINT);
|
||||
return ret;
|
||||
}
|
||||
101
execsnoop-kernel/readme.md
Normal file
101
execsnoop-kernel/readme.md
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
## Prons and cons
|
||||
|
||||
- use stable execve tracepoint, so build once and should work everywhere
|
||||
- need to build in kernel tree
|
||||
|
||||
## Build in kernel tree
|
||||
|
||||
- ready and config kernel tree
|
||||
|
||||
```bash
|
||||
# kernel config
|
||||
gunzip -c /proc/config.gz > .config
|
||||
make oldconfig && make prepare
|
||||
# install headers to ./usr/include
|
||||
make headers_install -j8
|
||||
# build bpf
|
||||
make M=samples/bpf -j8
|
||||
```
|
||||
|
||||
- put or link `execsnoop_kern.c` and `execsnoop_user.c` to *samples/bpf/*
|
||||
- edit *samples/bpf/makefile*
|
||||
|
||||
```makefile
|
||||
# in samples/bpf/makefile
|
||||
tprogs-y += execsnoop
|
||||
execsnoop-objs := bpf_load.o execsnoop_user.o $(TRACE_HELPERS)
|
||||
always-y += execsnoop_kern.o
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
cd samples/bpf
|
||||
sudo bash -c "ulimit -l unlimited && ./execsnoop"
|
||||
```
|
||||
|
||||
## Detail build command
|
||||
|
||||
using `make V=1 M=samples/bpf | tee -a log.txt` to get and filter following command
|
||||
|
||||
- build `execsnoop_kern.o`
|
||||
|
||||
```bash
|
||||
clang -nostdinc \
|
||||
-isystem /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include \
|
||||
-I./arch/x86/include \
|
||||
-I./arch/x86/include/generated \
|
||||
-I./include \
|
||||
-I./arch/x86/include/uapi \
|
||||
-I./arch/x86/include/generated/uapi \
|
||||
-I./include/uapi \
|
||||
-I./include/generated/uapi \
|
||||
-include ./include/linux/kconfig.h \
|
||||
-I./samples/bpf \
|
||||
-I./tools/testing/selftests/bpf/ \
|
||||
-I./tools/lib/ \
|
||||
-include asm_goto_workaround.h \
|
||||
-D__KERNEL__ -D__BPF_TRACING__ -Wno-unused-value -Wno-pointer-sign \
|
||||
-D__TARGET_ARCH_x86 -Wno-compare-distinct-pointer-types \
|
||||
-Wno-gnu-variable-sized-type-not-at-end \
|
||||
-Wno-address-of-packed-member -Wno-tautological-compare \
|
||||
-Wno-unknown-warning-option \
|
||||
-fno-stack-protector -g \
|
||||
-O2 -emit-llvm -c samples/bpf/execsnoop_kern.c \
|
||||
-o - | llc -march=bpf -filetype=obj -o samples/bpf/execsnoop_kern.o
|
||||
```
|
||||
|
||||
- build `execsnoop_user.o`
|
||||
|
||||
```bash
|
||||
gcc -Wall -O2 -Wmissing-prototypes -Wstrict-prototypes \
|
||||
-I./usr/include \
|
||||
-I./tools/testing/selftests/bpf/ \
|
||||
-I./tools/lib/ \
|
||||
-I./tools/include \
|
||||
-I./tools/perf \
|
||||
-DHAVE_ATTR_TEST=0 \
|
||||
-c -o samples/bpf/execsnoop_user.o samples/bpf/execsnoop_user.c
|
||||
```
|
||||
|
||||
- build `execsnoop`
|
||||
|
||||
```bash
|
||||
gcc -Wall -O2 -Wmissing-prototypes -Wstrict-prototypes \
|
||||
-I./usr/include \
|
||||
-I./tools/testing/selftests/bpf/ \
|
||||
-I./tools/lib/ \
|
||||
-I./tools/include \
|
||||
-I./tools/perf \
|
||||
-DHAVE_ATTR_TEST=0 \
|
||||
-o samples/bpf/execsnoop \
|
||||
samples/bpf/bpf_load.o samples/bpf/execsnoop_user.o \
|
||||
tools/testing/selftests/bpf/trace_helpers.o tools/lib/bpf/libbpf.a \
|
||||
-lelf -lz
|
||||
```
|
||||
|
||||
## Some resources
|
||||
|
||||
- [A thorough introduction to eBPF](https://lwn.net/Articles/740157/)
|
||||
- [Write eBPF program in pure C](http://terenceli.github.io/%E6%8A%80%E6%9C%AF/2020/01/18/ebpf-in-c)
|
||||
@@ -1,11 +1,21 @@
|
||||
|
||||
## Depency
|
||||
- libbpf
|
||||
- /usr/lib/libbpf.a
|
||||
- some head file
|
||||
- bpf
|
||||
- `/usr/bin/bpftool` to generate skeleton and dump btf
|
||||
## Resource
|
||||
|
||||
## Refer
|
||||
- [libbpf](https://github.com/libbpf/libbpf)
|
||||
- [libbpf-tools](https://github.com/iovisor/bcc/tree/master/libbpf-tools) examples use libbpf
|
||||
- [bpftool](https://www.archlinux.org/packages/community/x86_64/bpf/) to generate skeleton and dump btf
|
||||
|
||||
- https://facebookmicrosites.github.io/bpf/blog/2020/02/19/bpf-portability-and-co-re.html
|
||||
## Prons
|
||||
|
||||
- BPF CO-RE (Compile Once – Run Everywhere)
|
||||
- small memory usage
|
||||
|
||||
## Cons
|
||||
|
||||
- `vmlinux.h`does not contain `#define` etc. And often causes confilct with other headers to cause redifinition error
|
||||
- comment in code for different types is gone
|
||||
- need kernel built with `CONFIG_DEBUG_INFO_BTF=y`, while ubuntu 20.04 still not
|
||||
|
||||
## Build
|
||||
|
||||
- see *makefile*
|
||||
Reference in New Issue
Block a user