一、现象描述
采用cilium epbf框架开发的ebpf程序无法在系统上正常运行。
curtis@curtis-desktop:~$ cd work/
curtis@curtis-desktop:~/work$ ls
kmodule vfs_write_moitor
curtis@curtis-desktop:~/work$
curtis@curtis-desktop:~/work$ sudo ./vfs_write_moitor -filename=/mnt/kk -pid=10
[sudo] password for curtis:
2023/06/29 08:12:13 loading objects: field KprobeDoSysOpen: program kprobe_do_sys_open: apply CO-RE relocations: load kernel spec: no BTF found for kernel version 5.15.0-1032-raspi: not supported
二、支持BPF内核选项
CONFIG_BPF=y:启用BPF子系统,允许使用BPF功能。
CONFIG_BPF_SYSCALL=y:启用BPF系统调用,允许用户空间程序通过系统调用与内核交互。
CONFIG_NETFILTER_XT_MATCH_BPF=m:编译为模块的BPF扩展,允许在Netfilter框架中使用BPF进行数据包匹配。
CONFIG_NET_CLS_BPF=m:编译为模块的BPF分类器,允许使用BPF对数据包进行分类和处理。
CONFIG_NET_ACT_BPF=m:编译为模块的BPF动作器,允许使用BPF对数据包进行动作处理。
CONFIG_BPF_JIT=y:启用BPF即时编译器,提高BPF程序的执行效率。
CONFIG_HAVE_BPF_JIT=y:表示系统支持BPF即时编译器。
CONFIG_BPF_EVENTS=y:启用BPF事件通知机制,允许用户空间程序监控和处理BPF相关事件。
三、支持BTF/CO-RE内核选项
CONFIG_DEBUG_INFO_BTF=y
https://www.ebpf.top/post/btf-bpf-type-format/
3.1 BTF(BPF Type Format)
是一种用于描述BPF程序的数据结构格式。BPF是一种在Linux内核中运行的虚拟机,可以用于网络数据包过滤、系统调用跟踪、性能分析等方面。BTF可以帮助开发者更方便地编写BPF程序,因为它提供了一种类型安全的方式来访问内核数据结构。
3.2 CO-RE(Compile Once - Run Everywhere)
CO-RE是一种用于优化BPF程序加载和共享的技术。它可以将BPF程序的字节码和相关的元数据打包成一个可重定位的对象文件,然后在运行时动态加载和共享这个对象文件。这样可以避免重复编译和加载相同的BPF程序,从而提高系统的性能和可维护性。
CO-RE依赖BTF是因为BTF提供了BPF程序的类型信息,这对于CO-RE的优化和动态加载非常重要。CO-RE需要使用BTF来检查BPF程序的类型正确性,以及在运行时动态解析BPF程序的符号和类型信息。因此,BTF是CO-RE的一个重要组成部分。
https://www.ebpf.top/post/btfgen-one-step-closer-to-truly-portable-ebpf-programs/
CO-RE (一次编译 - 到处运行)
CO-RE 机制正是为解决上述问题提出的方案。在该方案中,eBPF 程序一次编译,然后在运行时进行更新(patched):基于运行的机器的内核结构布局更新运行指令。BPF CO-RE (Compile Once - Run Everywhere) 介绍了该技术背后的所有细节。对于本文,需要理解的是 CO-RE 需要有目标内核的 BTF 信息(BPF Type Format 类型格式)。BTF 信息由内核本身提供的,这需要在内核编译时设置 CONFIG_DEBUG_INFO_BTF=y 选项 。该选项在Linux 内核 5.2 中引入的,许多流行的 Linux 发行版在其后的部分内核版本才默认启用。这意味着有很多用户运行的内核并没有导出 BTF 信息,因此不能使用基于 CO-RE 的工具。
四、解决办法
开启对应的内核选项,重新替换内核即可正常运行ebpf程序,编译之前一定要反复确定CONFIG_DEBUG_INFO_BTF
选项被打开,可以通过查看.config配置文件。