如何通过eBPF程序修改内核函数执行结果及调用内核函数?
问题分析与解决方案
内核代码修改:让验证器识别自定义规则
你编写的all_verifier_ops结构体不会被内核自动加载,必须将其关联到你要使用的eBPF程序类型(比如kprobe/tracepoint)。以kprobe为例,直接修改net/core/filter.c中已有的kprobe_verifier_ops即可:
// 替换原有kprobe验证规则结构体 const struct bpf_verifier_ops kprobe_verifier_ops = { .check_kfunc_call = export_the_world, .is_valid_access = accept_the_world, .get_func_proto = bpf_tracing_func_proto, .struct_access_cb = bpf_tracing_struct_access, };
修改完成后重新编译内核并启动,kprobe类型的eBPF程序就会使用你的自定义验证规则,允许调用任意内核函数。
BCC报错原因与修复
你遇到的报错是因为BCC的代码生成逻辑不支持直接调用非BPF helper的内核函数,且KFUNC_PROBE是用于追踪内核函数的探针宏,不是用来主动调用函数的。这类复杂场景更适合用libbpf而非BCC,以下是可运行的libbpf示例:
1. eBPF程序(test.bpf.c)
#include <vmlinux.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h> // 声明要调用的内核函数,__ksym标记为内核符号 extern void hello_test_kfunc(void) __ksym; // kprobe追踪vfs_open SEC("kprobe/vfs_open") int BPF_KPROBE(vfs_open, const struct path *path, struct file *file) { // 调用自定义内核函数 hello_test_kfunc(); // 示例:修改vfs_open的返回值(需匹配函数实际原型) // bpf_set_retval(0); return 0; } char _license[] SEC("license") = "GPL";
2. 用户态加载程序(test.c)
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <libbpf/libbpf.h> #include "test.skel.h" static volatile bool exiting = false; static void sig_handler(int sig) { exiting = true; } int main(int argc, char **argv) { struct test_bpf *skel; int err; signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); // 加载并验证eBPF程序 skel = test_bpf__open_and_load(); if (!skel) { fprintf(stderr, "Failed to open and load BPF skeleton\n"); return 1; } // 附加kprobe err = test_bpf__attach(skel); if (err) { fprintf(stderr, "Failed to attach BPF skeleton: %d\n", err); goto cleanup; } printf("Running... Press Ctrl+C to exit\n"); while (!exiting) { sleep(1); } cleanup: test_bpf__destroy(skel); return err < 0 ? -err : 0; }
3. 编译与运行
# 编译eBPF字节码 clang -target bpf -D__TARGET_ARCH_x86_64 -I/usr/include/x86_64-linux-gnu -O2 -c test.bpf.c -o test.bpf.o # 生成skeleton头文件 bpftool gen skeleton test.bpf.o > test.skel.h # 编译用户态程序 gcc -o test test.c -lbpf -lelf -lz # 以root权限运行 sudo ./test
关键注意事项
- 修改内核后,可用
bpftool feature probe验证kfunc调用权限是否生效。 - 开放所有内核函数调用存在极高安全风险,仅用于测试环境,生产环境严禁使用。
- 若要修改内核函数执行结果,除调用其他内核函数外,还可直接用
bpf_set_retval()(kprobe场景)修改返回值。
内容的提问来源于stack exchange,提问作者hfingler
相关产品推荐
相关产品推荐

