BPF LSM问题:bpf_task_storage_get期望可信指针
问题:LSM BPF程序中
bpf_task_storage_get无法识别bpf_get_current_task()返回的指针 现象
在LSM的task_alloc钩子中,使用bpf_get_current_task()获取当前任务指针并传入bpf_task_storage_get时,BPF程序加载失败。BPF验证器提示第二个参数为标量,不符合指针/可信指针的要求。
可正常运行的代码
struct provenance_structure { __u8 to_trace; struct bpf_spin_lock lock; }; struct { __uint(type, BPF_MAP_TYPE_TASK_STORAGE); __uint(map_flags, BPF_F_NO_PREALLOC); __type(key, int); __type(value, struct provenance_structure); } provenance_structure_map_task SEC(".maps"); SEC("lsm/task_alloc") int BPF_PROG(task_allocation, struct task_struct *p, u64 clone_flags) { struct provenance_structure *prov; prov = bpf_task_storage_get(&provenance_structure_map_task, p, NULL, 0); if(prov){ bpf_spin_lock(&prov->lock); prov->to_trace = 1; bpf_spin_unlock(&prov->lock); } return 0; }
出错的代码
SEC("lsm/task_alloc") int BPF_PROG(task_allocation, struct task_struct *p, u64 clone_flags) { // 强制转换为struct task_struct*也会触发相同错误 struct task_struct *s_task = (void *)bpf_get_current_task(); struct provenance_structure *prov; prov = bpf_task_storage_get(&provenance_structure_map_task, s_task, NULL, 0); if(prov){ bpf_spin_lock(&prov->lock); // 将to_trace标记设为True prov->to_trace = 1; bpf_spin_unlock(&prov->lock); } return 0; }
验证器错误日志
libbpf: prog 'task_allocation': -- BEGIN PROG LOAD LOG -- 0: R1=ctx() R10=fp0 ; struct task_struct *s_task = (void *)bpf_get_current_task(); @ provenance_tracing_programs.bpf.c:139 0: (85) call bpf_get_current_task#35 ; R0_w=scalar() ; prov = bpf_task_storage_get(&provenance_structure_map_task, s_task, NULL, 0); @ provenance_tracing_programs.bpf.c:141 1: (18) r1 = 0xffff9a96d1220200 ; R1_w=map_ptr(map=provenance_stru,ks=4,vs=272) 3: (bf) r2 = r0 ; R0_w=scalar(id=1) R2_w=scalar(id=1) 4: (b7) r3 = 0 ; R3_w=0 5: (b7) r4 = 0 ; R4_w=0 6: (85) call bpf_task_storage_get#156 R2 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_ processed 6 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0 -- END PROG LOAD LOG -- libbpf: prog 'task_allocation': failed to load: -13 libbpf: failed to load object 'provenance_tracing_programs_bpf' failed to load BPF object: -13
原因
bpf_get_current_task()返回的是无类型的标量指针,BPF验证器无法确认其指向struct task_struct,也不会将其标记为可信指针(trusted_ptr)。而LSM钩子参数中的p是内核直接传递的,验证器已确认其类型和可信度,因此可以正常使用。
解决方案
使用bpf_get_current_task_btf()替代bpf_get_current_task(),该函数返回带有BTF类型信息的struct task_struct*指针,验证器会识别其为可信指针,允许传递给bpf_task_storage_get。
修改后的代码:
SEC("lsm/task_alloc") int BPF_PROG(task_allocation, struct task_struct *p, u64 clone_flags) { struct task_struct *s_task = bpf_get_current_task_btf(); struct provenance_structure *prov; prov = bpf_task_storage_get(&provenance_structure_map_task, s_task, NULL, 0); if(prov){ bpf_spin_lock(&prov->lock); prov->to_trace = 1; bpf_spin_unlock(&prov->lock); } return 0; }
注意事项
bpf_get_current_task_btf()需要内核版本5.15及以上支持。- 确保编译环境启用了BTF(较新内核发行版默认已开启)。
内容的提问来源于stack exchange,提问作者Polo
相关产品推荐
相关产品推荐

