forked from eunomia-bpf/bpftime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
runtime: support map type
perf_event_array
(eunomia-bpf#20)
* Initial logging * Simply adds a header and source * Implement perf_event_array_map * Rename perf_event_array * Implement software perf event * Reconstruct something * Update changes * Update * Update * Update * Update * Update * update * Fix CI * Update munmap * Update a header * Update example: statsnoop
- Loading branch information
1 parent
ed46dc9
commit f072961
Showing
36 changed files
with
2,720 additions
and
826 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.vscode | ||
package.json | ||
*.o | ||
*.skel.json | ||
*.skel.yaml | ||
package.yaml | ||
ecli | ||
bootstrap | ||
.output | ||
opensnoop | ||
victim | ||
test.txt | ||
syscall-trace.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | ||
OUTPUT := .output | ||
CLANG ?= clang | ||
LIBBPF_SRC := $(abspath ../../third_party/libbpf/src) | ||
BPFTOOL_SRC := $(abspath ../../third_party/bpftool/src) | ||
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) | ||
BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) | ||
BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool | ||
ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \ | ||
| sed 's/arm.*/arm/' \ | ||
| sed 's/aarch64/arm64/' \ | ||
| sed 's/ppc64le/powerpc/' \ | ||
| sed 's/mips.*/mips/' \ | ||
| sed 's/riscv64/riscv/' \ | ||
| sed 's/loongarch64/loongarch/') | ||
VMLINUX := ../../third_party/vmlinux/$(ARCH)/vmlinux.h | ||
# Use our own libbpf API headers and Linux UAPI headers distributed with | ||
# libbpf to avoid dependency on system-wide headers, which could be missing or | ||
# outdated | ||
INCLUDES := -I$(OUTPUT) -I../../third_party/libbpf/include/uapi -I$(dir $(VMLINUX)) | ||
CFLAGS := -g -Wall | ||
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) | ||
|
||
APPS = opensnoop # minimal minimal_legacy uprobe kprobe fentry usdt sockfilter tc ksyscall | ||
|
||
CARGO ?= $(shell which cargo) | ||
ifeq ($(strip $(CARGO)),) | ||
BZS_APPS := | ||
else | ||
BZS_APPS := # profile | ||
APPS += $(BZS_APPS) | ||
# Required by libblazesym | ||
ALL_LDFLAGS += -lrt -ldl -lpthread -lm | ||
endif | ||
|
||
# Get Clang's default includes on this system. We'll explicitly add these dirs | ||
# to the includes list when compiling with `-target bpf` because otherwise some | ||
# architecture-specific dirs will be "missing" on some architectures/distros - | ||
# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h, | ||
# sys/cdefs.h etc. might be missing. | ||
# | ||
# Use '-idirafter': Don't interfere with include mechanics except where the | ||
# build would have failed anyways. | ||
CLANG_BPF_SYS_INCLUDES ?= $(shell $(CLANG) -v -E - </dev/null 2>&1 \ | ||
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') | ||
|
||
ifeq ($(V),1) | ||
Q = | ||
msg = | ||
else | ||
Q = @ | ||
msg = @printf ' %-8s %s%s\n' \ | ||
"$(1)" \ | ||
"$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \ | ||
"$(if $(3), $(3))"; | ||
MAKEFLAGS += --no-print-directory | ||
endif | ||
|
||
define allow-override | ||
$(if $(or $(findstring environment,$(origin $(1))),\ | ||
$(findstring command line,$(origin $(1)))),,\ | ||
$(eval $(1) = $(2))) | ||
endef | ||
|
||
$(call allow-override,CC,$(CROSS_COMPILE)cc) | ||
$(call allow-override,LD,$(CROSS_COMPILE)ld) | ||
|
||
.PHONY: all | ||
all: $(APPS) victim | ||
|
||
.PHONY: clean | ||
clean: | ||
$(call msg,CLEAN) | ||
$(Q)rm -rf $(OUTPUT) $(APPS) | ||
|
||
$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT): | ||
$(call msg,MKDIR,$@) | ||
$(Q)mkdir -p $@ | ||
|
||
# Build libbpf | ||
$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf | ||
$(call msg,LIB,$@) | ||
$(Q)$(MAKE) -C $(LIBBPF_SRC) CFLAGS="-O0 -g" BUILD_STATIC_ONLY=1 \ | ||
OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \ | ||
INCLUDEDIR= LIBDIR= UAPIDIR= \ | ||
install | ||
|
||
# Build bpftool | ||
$(BPFTOOL): | $(BPFTOOL_OUTPUT) | ||
$(call msg,BPFTOOL,$@) | ||
$(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap | ||
|
||
|
||
$(LIBBLAZESYM_SRC)/target/release/libblazesym.a:: | ||
$(Q)cd $(LIBBLAZESYM_SRC) && $(CARGO) build --features=cheader,dont-generate-test-files --release | ||
|
||
$(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) | ||
$(call msg,LIB, $@) | ||
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/libblazesym.a $@ | ||
|
||
$(LIBBLAZESYM_HEADER): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) | ||
$(call msg,LIB,$@) | ||
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/blazesym.h $@ | ||
|
||
# Build BPF code | ||
$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) | ||
$(call msg,BPF,$@) | ||
$(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \ | ||
$(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \ | ||
-c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@) | ||
$(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@) | ||
|
||
# Generate BPF skeletons | ||
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) | ||
$(call msg,GEN-SKEL,$@) | ||
$(Q)$(BPFTOOL) gen skeleton $< > $@ | ||
|
||
# Build user-space code | ||
$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h | ||
|
||
$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT) | ||
$(call msg,CC,$@) | ||
$(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ | ||
|
||
$(patsubst %,$(OUTPUT)/%.o,$(BZS_APPS)): $(LIBBLAZESYM_HEADER) | ||
|
||
$(BZS_APPS): $(LIBBLAZESYM_OBJ) | ||
|
||
# Build application binary | ||
$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) | ||
$(call msg,BINARY,$@) | ||
$(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ | ||
|
||
# delete failed targets | ||
.DELETE_ON_ERROR: | ||
|
||
# keep intermediate (.skel.h, .bpf.o, etc) targets | ||
.SECONDARY: | ||
|
||
victim: victim.cpp | ||
$(CXX) victim.cpp -Wall -g -o victim |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# opensnoop | ||
|
||
Not working because we refactored the runtime. | ||
|
||
TODO: make the ring buffer work again. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
// Copyright (c) 2019 Facebook | ||
// Copyright (c) 2020 Netflix | ||
#include <vmlinux.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include "opensnoop.h" | ||
|
||
const volatile pid_t targ_pid = 0; | ||
const volatile pid_t targ_tgid = 0; | ||
const volatile uid_t targ_uid = 0; | ||
const volatile bool targ_failed = false; | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_HASH); | ||
__uint(max_entries, 10240); | ||
__type(key, u32); | ||
__type(value, struct args_t); | ||
} start 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; | ||
} | ||
|
||
static __always_inline | ||
bool trace_allowed(u32 tgid, u32 pid) | ||
{ | ||
u32 uid; | ||
|
||
/* filters */ | ||
if (targ_tgid && targ_tgid != tgid) | ||
return false; | ||
if (targ_pid && targ_pid != pid) | ||
return false; | ||
if (valid_uid(targ_uid)) { | ||
uid = (u32)bpf_get_current_uid_gid(); | ||
if (targ_uid != uid) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_enter_open") | ||
int tracepoint__syscalls__sys_enter_open(struct trace_event_raw_sys_enter* ctx) | ||
{ | ||
u64 id = bpf_get_current_pid_tgid(); | ||
/* use kernel terminology here for tgid/pid: */ | ||
u32 tgid = id >> 32; | ||
u32 pid = id; | ||
|
||
/* store arg info for later lookup */ | ||
if (trace_allowed(tgid, pid)) { | ||
struct args_t args = {}; | ||
args.fname = (const char *)ctx->args[0]; | ||
args.flags = (int)ctx->args[1]; | ||
bpf_map_update_elem(&start, &pid, &args, 0); | ||
} | ||
return 0; | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_enter_openat") | ||
int tracepoint__syscalls__sys_enter_openat(struct trace_event_raw_sys_enter* ctx) | ||
{ | ||
u64 id = bpf_get_current_pid_tgid(); | ||
/* use kernel terminology here for tgid/pid: */ | ||
u32 tgid = id >> 32; | ||
u32 pid = id; | ||
|
||
/* store arg info for later lookup */ | ||
if (trace_allowed(tgid, pid)) { | ||
struct args_t args = {}; | ||
args.fname = (const char *)ctx->args[1]; | ||
args.flags = (int)ctx->args[2]; | ||
bpf_map_update_elem(&start, &pid, &args, 0); | ||
} | ||
return 0; | ||
} | ||
|
||
static __always_inline | ||
int trace_exit(struct trace_event_raw_sys_exit* ctx) | ||
{ | ||
struct event event = {}; | ||
struct args_t *ap; | ||
uintptr_t stack[3]; | ||
int ret; | ||
u32 pid = bpf_get_current_pid_tgid(); | ||
|
||
ap = bpf_map_lookup_elem(&start, &pid); | ||
if (!ap) | ||
return 0; /* missed entry */ | ||
ret = ctx->ret; | ||
if (targ_failed && ret >= 0) | ||
goto cleanup; /* want failed only */ | ||
|
||
/* event data */ | ||
event.pid = bpf_get_current_pid_tgid() >> 32; | ||
event.uid = bpf_get_current_uid_gid(); | ||
bpf_get_current_comm(&event.comm, sizeof(event.comm)); | ||
bpf_probe_read_user_str(&event.fname, sizeof(event.fname), ap->fname); | ||
event.flags = ap->flags; | ||
event.ret = ret; | ||
|
||
bpf_get_stack(ctx, &stack, sizeof(stack), | ||
BPF_F_USER_STACK); | ||
/* Skip the first address that is usually the syscall it-self */ | ||
event.callers[0] = stack[1]; | ||
event.callers[1] = stack[2]; | ||
|
||
/* emit event */ | ||
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, | ||
&event, sizeof(event)); | ||
|
||
cleanup: | ||
bpf_map_delete_elem(&start, &pid); | ||
return 0; | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_exit_open") | ||
int tracepoint__syscalls__sys_exit_open(struct trace_event_raw_sys_exit* ctx) | ||
{ | ||
return trace_exit(ctx); | ||
} | ||
|
||
SEC("tracepoint/syscalls/sys_exit_openat") | ||
int tracepoint__syscalls__sys_exit_openat(struct trace_event_raw_sys_exit* ctx) | ||
{ | ||
return trace_exit(ctx); | ||
} | ||
|
||
char LICENSE[] SEC("license") = "GPL"; |
Oops, something went wrong.