【发布时间】:2020-07-16 13:36:05
【问题描述】:
我编写了一个简单的程序来使用 kprobe 附加到 execve 系统调用,但我无法看到相关的输出。
这是我的 one.c(BPF 程序):
#include <errno.h>
#include <bpf/bpf.h>
#include <stdio.h>
#include <string.h>
#include "bpf_load.h"
#include "bpf_util.h"
#include "libbpf.h"
#define SEC(NAME) __attribute__((section(NAME), used))
SEC("kprobe/execve")
int bpf_prog1(struct pt_regs *ctx)
{
char m[]="hello world";
bpf_trace_printk(m,sizeof(m));
return 0;
}
char _license[] SEC("license") = "GPL";
bpf_load.c(用户空间加载器):
#include "bpf_load.h"
#include <stdio.h>
#include <linux/bpf.h>
#include <sys/resource.h>
int main(int argc, char **argv) {
if (load_bpf_file("one.o")) {
printf("%s", bpf_log_buf);
return 1;
}
return 0;
}
还有 Makefile:
CLANG = clang
EXECABLE = monitor-exec
BPFCODE = one
BPFTOOLS = /kernel-src/samples/bpf
BPFLOADER = $(BPFTOOLS)/bpf_load.c
INCLUDE += -I/kernel-src/samples/bpf
INCLUDE += -I/kernel-src/tools/lib
CCINCLUDE += -I/kernel-src/tools/testing/selftests/bpf
CCINCLUDE += -I/kernel-src/tools/lib/bpf
CCINCLUDE += ${INCLUDE}
LOADINCLUDE += -I/kernel-src/tools/include
LOADINCLUDE += -I/kernel-src/tools/perf
LOADINCLUDE += ${INCLUDE}
LIBRARY_PATH = -L/usr/local/lib64
BPFSO = -lbpf
.PHONY: clean bpfload build
clean:
rm -f *.o *.so $(EXECABLE)
build: ${BPFCODE.c} ${BPFLOADER}
$(CLANG) -O2 -DHAVE_ATTR_TEST=0 -target bpf -c $(BPFCODE:=.c) $(CCINCLUDE) -o ${BPFCODE:=.o}
bpfload: build
clang -o $(EXECABLE) -DHAVE_ATTR_TEST=0 -lelf $(LOADINCLUDE) $(LIBRARY_PATH) $(BPFSO) \
$(BPFLOADER) loader.c
$(EXECABLE): bpfload
.DEFAULT_GOAL := $(EXECABLE)
到目前为止,我没有从 Makefile 中得到任何错误。
当我执行./monitor-exec时得到以下输出
invalid relo for insn[6].code 0x85
bpf_load_program() err=22
last insn is not an exit or jmp
processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
last insn is not an exit or jmp
processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
我无法理解我做错了什么。我只是附加了一个 kprobe,当该系统调用发生时,它应该打印 hello world。
【问题讨论】:
-
您的程序从哪里选择
bpf_trace_printk()的定义?当 libbpf 尝试对您的目标文件执行重定位时,它似乎不知道在哪里找到它。 -
那我该怎么办?我是新手..所以据我了解
bpf_trace_printk()定义不在我的程序中,对吗? -
我不确定,因为它可能在您包含的文件之一中。但是您可以尝试在您的 BPF 程序文件中手动添加它:
static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) = (void *) BPF_FUNC_trace_printk;(这将声明基于 linux/bpf.h 中定义的BPF_FUNC_trace_printk枚举成员的函数,我认为包含在 bpf/bpf.h 中)。 -
好的,谢谢....我还有一个问题
failed to create kprobe 'execve' error 'No such file or directory',如何知道在kprobe/或其他类似uprobe、tracepoint 之后支持的所有系统调用类型... -
几乎所有内核函数都可以被追踪(只要它们在编译时没有被内联)。您可能想检查
sudo cat /proc/kallsyms|grep execve之类的可用符号。尽管对于系统调用,我们通常建议使用跟踪点而不是 kprobes,因为它们更稳定(在内核版本之间)。在您的情况下,您可以使用一个名为sys_enter_execve的跟踪点。