首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将eBPF附加到KPROBE上?

将eBPF附加到KPROBE上?
EN

Stack Overflow用户
提问于 2020-07-16 13:36:05
回答 1查看 2.2K关注 0票数 2

我编写了一个简单的程序来附加到execve系统调用,但是我无法看到相关的输出。

这里是我的第一个c (BPF程序):

代码语言:javascript
复制
#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 (用户空间加载器):

代码语言:javascript
复制
#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:

代码语言:javascript
复制
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时,我将得到以下输出

代码语言:javascript
复制
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

我无法理解我做错了什么。我只是附加一个k探头,当系统调用发生时,应该打印hello world

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-16 13:39:45

在您的eBPF程序中:

代码语言:javascript
复制
#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;
}

您正确地使用了bpf_trace_printk() (虽然您可能希望在消息的末尾添加一个\n,或者您的输出会很混乱),但是您所包含的文件中没有一个包含此助手的定义。

bpf_trace_printk()是作为内核的一部分编译的,永远不会编译到您的BPF对象文件中。当尝试加载程序时,函数load_bpf_file()执行重定位步骤,它将与bpf_trace_printk()关联的数字(在用户API中)放置在eBPF字节码的相关指令中。

但它需要在某个地方找到这个号码。它在头linux/bpf.h (从多个包含中提取)中定义为FN(trace_printk) (正在进行的一些宏魔术),结果实际上是一个#define BPF_FUNC_trace_prink 6。但是,您需要告诉加载函数它对应于您正在调用的bpf_trace_prink()

有两种解决办法:

  • 手动声明:静态int (*bpf_trace_printk)(const *fmt,int fmt_size,.)= (void *) BPF_FUNC_trace_printk;
  • 或者添加一个包含它的头,例如内核回购中的tools/lib/bpf/bpf_helpers.h。在您的例子中:#include (请注意,此标头在编译libbpf时是已生成,默认情况下它不在存储库中。)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62936008

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档