编写lsm/file_open eBPF程序时BPF验证器拒绝bpf_d_path参数的问题
问题:挂载
lsm/file_open的eBPF程序被BPF验证器拒绝 我编写了一个挂载到lsm/file_open的eBPF示例程序,但加载时被BPF验证器拒绝,内核版本为6.8.0-51-generic。
我的eBPF程序代码
#include "vmlinux.h" #include "commons.h" #include <bpf/bpf_helpers.h> #include <bpf/bpf_core_read.h> #include <bpf/bpf_tracing.h> #define MAX_SIZE 255 SEC("lsm/file_open") int BPF_PROG(test_prog, struct file *file, int ret) { unsigned int f_flags; struct path file_path; char path_buffer[MAX_SIZE]; BPF_CORE_READ_INTO(&file_path, file, f_path); long err = bpf_d_path(&file_path, path_buffer, sizeof(path_buffer)); return 0; } char LICENSE[] SEC("license") = "GPL";
BPF验证器输出
libbpf: prog 'test_prog': BPF program load failed: Permission denied libbpf: prog 'test_prog': -- BEGIN PROG LOAD LOG -- 0: R1=ctx() R10=fp0 ; int BPF_PROG(test_prog, struct file *file, int ret) 0: (b7) r2 = 152 ; R2_w=152 ; int BPF_PROG(test_prog, struct file *file, int ret) 1: (79) r3 = *(u64 *)(r1 +0) func 'bpf_lsm_file_open' arg0 has btf_id 601 type STRUCT 'file' 2: R1=ctx() R3_w=trusted_ptr_file() 2: (0f) r3 += r2 ; R2_w=152 R3_w=trusted_ptr_file(off=152) 3: (bf) r6 = r10 ; R6_w=fp0 R10=fp0 ; 4: (07) r6 += -16 ; R6_w=fp-16 ; BPF_CORE_READ_INTO(&file_path, file, f_path); 5: (bf) r1 = r6 ; R1_w=fp-16 R6_w=fp-16 6: (b7) r2 = 16 ; R2_w=16 7: (85) call bpf_probe_read_kernel#113 ; R0_w=scalar() fp-8=mmmmmmmm fp-16=mmmmmmmm 8: (bf) r2 = r10 ; R2_w=fp0 R10=fp0 ; 9: (07) r2 += -271 ; R2_w=fp-271 ; long err = bpf_d_path(&file_path, path_buffer, sizeof(path_buffer)); 10: (bf) r1 = r6 ; R1_w=fp-16 R6_w=fp-16 11: (b7) r3 = 255 ; R3_w=255 12: (85) call bpf_d_path#147 R1 type=fp expected=ptr_, trusted_ptr_, rcu_ptr_ processed 13 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0 -- END PROG LOAD LOG -- libbpf: prog 'test_prog': failed to load: -13 libbpf: failed to load object 'lsm_file_open.o' Failed to load BPF object into the kernel
错误原因与修复方案
错误原因
验证器报错R1 type=fp expected=ptr_, trusted_ptr_, rcu_ptr_,核心问题是:bpf_d_path的第一个参数要求传入内核空间的可信指针(如trusted_ptr_类型),但原代码传递的是eBPF栈上变量file_path的地址(fp类型,即栈指针),不符合内核验证规则。
修复后的代码
#include "vmlinux.h" #include "commons.h" #include <bpf/bpf_helpers.h> #include <bpf/bpf_core_read.h> #include <bpf/bpf_tracing.h> #define MAX_SIZE 255 SEC("lsm/file_open") int BPF_PROG(test_prog, struct file *file, int ret) { char path_buffer[MAX_SIZE]; // 直接获取内核中file->f_path的可信指针,无需拷贝到栈 const struct path *file_path = BPF_CORE_READ(file, f_path); long err = bpf_d_path(file_path, path_buffer, sizeof(path_buffer)); return 0; } char LICENSE[] SEC("license") = "GPL";
修复说明
通过BPF_CORE_READ(file, f_path)直接获取内核中struct file成员f_path的指针,该指针属于内核认可的可信指针类型,能通过BPF验证器的检查,同时避免了不必要的栈拷贝操作。
内容的提问来源于stack exchange,提问作者Kamran
相关产品推荐
相关产品推荐

