使用BCC加载XDP程序报错

XDP加载失败libbpf: failed to find valid kernel BTF,内核 BTF 未找到或不可用

报错:

$ sudo ip link set dev eth0 xdp obj xdp.bpf.o sec xdp libbpf

libbpf: failed to find valid kernel BTF

libbpf: Error loading vmlinux BTF: -3

libbpf: failed to load object 'xdp.bpf.o'

解决办法:

1、升级内核*(行不通)

# Ubuntu/Debian
sudo apt install linux-image-5.15.0-78-generic
sudo reboot

原因:由于缺少有效的内核BTF(BPF Type Format)信息。BTF是BPF程序所需的内核调试符号信息,用于帮助加载和执行BPF程序。该错误表明 libbpf 无法找到有效的内核BTF,或者在加载BTF时发生了错误。

2、启用内核编译。

2.1检查是否有btf

ls /sys/kernel/btf  #如果该目录下没有文件,表示当前内核没有BTF信息

2.2安装 linux-headers 和 BTF 文件

sudo apt-get install linux-headers-$(uname -r)

2.3  使用 bpftool 获取BTF信息

sudo bpftool btf dump file /sys/kernel/btf/vmlinux #这会将BTF信息转储到指定的文件,如果没有要重新编译内核

2.4 使用 objcopy 提取BTF信息

pahole -J vmlinux #pahole 是一个专门用来生成BTF符号的工具。生成的BTF文件可以在加载BPF程序时作为参数传递给 libbpf,,如果你有内核的vmlinux文件(通常位于/usr/src/linux/下)

报错:$ pahole -J vmlinux

Command 'pahole' not found, but can be installed with: sudo apt install pahole

解决:sudo apt install pahole

继续执行:pahole -J vmlinux

报错:pahole: vmlinux: Invalid argument

2.5  vmlinux 文件是从内核源代码编译生成的,它包含了内核的符号信息,通常用于调试和分析BPF程序。系统上没有 vmlinux 文件,并且没有安装内核源代码,按照以下步骤获取并编译它。

sudo apt-get install linux-source

2.6 解压文件

sudo tar -xjf linux-source-5.15.0.tar.bz2

2.7进入解压后的的内核源代码目录

cd /usr/src/linux-source-5.15.0

2.8 安装依赖包

sudo apt-get install build-essential libncurses-dev bison flex libssl-dev

 2.9初始化内核

sudo make defconfig  #初始化内核配置

报错:

wei@wei-virtual-machine:/usr/src/linux-source-5.15.0/linux-source-5.15.0$ sudo make defconfig HOSTCC scripts/basic/fixdep HOSTCC scripts/kconfig/conf.o HOSTCC scripts/kconfig/confdata.o HOSTCC scripts/kconfig/expr.o LEX scripts/kconfig/lexer.lex.c /bin/sh: 1: flex: not found make[1]: *** [scripts/Makefile.host:9: scripts/kconfig/lexer.lex.c] Error 127 make: *** [Makefile:630: defconfig] Error

解决:

 sudo apt-get install flex

如果遇到其他类似的错误,可能是因为缺少其他编译工具。你可以通过安装常见的编译工具来解决这些问题:

sudo apt-get install build-essential libncurses-dev bison flex libssl-dev
 

3 配置内核

make menuconfig

#配置菜单中依次选择下面的选项
Kernel hacking -> Compile-time checks and compiler options -> Compile the kernel with debug info (CONFIG_DEBUG_INFO)

#Compile the kernel with debug info菜单下面选择与BTF有关的选项。最后保存,退出。

 4 编译内核

sudo make

报错:

  CC      security/selinux/avc.o
  CC      security/selinux/hooks.o
  CC      security/selinux/selinuxfs.o
security/selinux/selinuxfs.c: In function ‘exit_sel_fs’:
security/selinux/selinuxfs.c:2260:22: error: ‘selinuxfs_mount’ undeclared (first use in this function)
 2260 |         kern_unmount(selinuxfs_mount);
      |                      ^~~~~~~~~~~~~~~
security/selinux/selinuxfs.c:2260:22: note: each undeclared identifier is reported only once for each function it appears in
make[2]: *** [scripts/Makefile.build:297: security/selinux/selinuxfs.o] Error 1
make[1]: *** [scripts/Makefile.build:560: security/selinux] Error 2
make: *** [Makefile:1910: security] Error 2
 

解决办法:

# 进入内核源码目录
cd /usr/src/linux-source-5.15.0/linux-source-5.15.0

# 使用 sudo 编辑文件
sudo nano security/selinux/selinuxfs.c

这是selinxfs.c第2257行代码,void exit_sel_fs(void)
{
sysfs_remove_mount_point(fs_kobj, "selinux");
dput(selinux_null.dentry);
kern_unmount(selinuxfs_mount);
unregister_filesystem(&sel_fs_type);
把上面(selinuxfs_mount)修改成selinux_fs_mount)
保存退出。

还要继续找到kern_unmount(selinuxfs_mount);将其修改为:
kern_unmount(selinux_fs_mount);

#直接使用命令修改:
wei@wei-virtual-machine:/usr/src/linux-source-5.15.0/linux-source-5.15.0/security/selinux$ sudo sed -i 's/kern_unmount(selinuxfs_mount);/kern_unmount(selinux_fs_mount),/' selinuxfs.c

以上修改后又报错:

变量没有声明。

 void exit_sel_fs(void)
{
sysfs_remove_mount_point(fs_kobj, "selinux");
dput(selinux_null.dentry);
kern_unmount(selinuxfs_mount);
unregister_filesystem(&sel_fs_type);

保留源代码中的命名selinuxfs_mount。下面进行代码声明:

直接在void exit_sel_fs(void)前面加一行声明:static struct selinux_fs_info *selinux_fs_info;

出现报错:

security/selinux/selinuxfs.c: In function ‘exit_sel_fs’: security/selinux/selinuxfs.c:2259:22: error: passing argument 1 of ‘kern_unmount’ from incompatible pointer type [-Werror=incompatible-pointer-types] 2259 | kern_unmount(selinuxfs_mount); | ^~~~~~~~~~~~~~~ | | | struct super_block * In file included from ./include/linux/huge_mm.h:8, from ./include/linux/mm.h:727, from ./include/linux/pagemap.h:8, from security/selinux/selinuxfs.c:16: ./include/linux/fs.h:2617:43: note: expected ‘struct vfsmount *’ but argument is of type ‘struct super_block *’ 2617 | extern void kern_unmount(struct vfsmount *mnt); | ~~~~~~~~~~~~~~~^ CC arch/x86/kernel/traps.o CC mm/interval_tree.o CC fs/proc/version.o CC crypto/proc.o CC fs/proc/softirqs.o CC security/integrity/iint.o CC crypto/aead.o CC kernel/dma/direct.o cc1: some warnings being treated as errors make[2]: *** [scripts/Makefile.build:297: security/selinux/selinuxfs.o] Error 1 make[1]: *** [scripts/Makefile.build:560: security/selinux] Error 2

又又报错

在Linux内核代码中,要声明一个struct vfsmount类型的变量,通常需要包含相应的头文件,并按照内核的命名约定进行声明。以下是如何声明selinuxfs_mount变量 

1、检查selinuxfs.c文件开头确保有:

#include <linux/fs.h>
#include <linux/mount.h>
 2、在全局或模块级别声明selinuxfs_mount变量:

struct vfsmount *selinuxfs_mount;

3、找到最后面代码,修改成:

void exit_sel_fs(void) { sysfs_remove_mount_point(fs_kobj, "selinux"); dput(selinux_null.dentry); // 确保在调用kern_unmount之前,selinuxfs_mount已经正确初始化 if (selinuxfs_mount) { kern_unmount(selinuxfs_mount); } unregister_filesystem(&sel_fs_type); }

继续编译: 

# 清理旧编译产物
make clean
# 重新编译
make -j$(nproc)

 成功编译,没有报错!

这是selinux文件目录:

4.1 安装内核模块和生成BTF

sudo make modules_install
sudo make install

4.2 内核模块生成了 BTF 信息 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值