重构TC eBPF程序触发map值访问权限错误的解决求助
TC环境eBPF程序重构内联函数后的内存访问错误修复
问题场景
我在编写TC环境下处理数据包的eBPF程序,定义的BPF映射如下:
struct value { int index; char flags[MAX_FLAGS_LEN]; }; struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, 32); __type(key, __u8); __type(value, struct value); } output_map SEC(".maps");
当所有逻辑都写在主处理函数中时,程序运行正常:
SEC("classifier") int tc_ingress(struct __sk_buff *skb) { __u8 key = 1; struct value *value; value = bpf_map_lookup_elem(&output_map, &key); if (value == NULL){ struct value initial_value = { .index = 1, .flags = "," }; bpf_map_update_elem(&output_map, &key, &initial_value, BPF_NOEXIST); } else { if (value->index >= sizeof(value->flags)){ goto out; } } if (value->index < sizeof(value->flags)){ value->flags[value->index] = ','; value->index++; } if (value->index < sizeof(value->flags)){ value->flags[value->index] = ','; value->index++; } bpf_printk("Flags: %d", value->flags); out: return TC_ACT_OK; }
但将逻辑提取为store_flags内联函数后,出现以下错误:
permission denied: invalid access to map value, value_size=20 off=20 size=1: R4 max value is outside of the allowed memory range (52 line(s) omitted)
修复方案及代码
问题根源是BPF验证器无法追踪内联函数中value->index的递增值对数组边界的约束。修复时先将value->index赋值给局部变量,用局部变量完成边界检查和索引操作,最后把更新后的局部变量写回value->index,让验证器能正确识别内存访问的合法性。
修复后的代码如下:
static __always_inline void store_flags(struct value *value){ int index = value->index; if (index < sizeof(value->flags)){ value->flags[index] = ','; index++; } if (index < sizeof(value->flags)){ value->flags[index] = ','; index++; } value->index=index; } SEC("classifier") int tc_ingress(struct __sk_buff *skb) { __u8 key = 1; struct value *value; value = bpf_map_lookup_elem(&output_map, &key); if (value == NULL){ struct value initial_value = { .index = 1, .flags = "," }; bpf_map_update_elem(&output_map, &key, &initial_value, BPF_NOEXIST); } else { store_flags(value); } bpf_printk("Flags: %d", value->flags); return TC_ACT_OK; }
内容的提问来源于stack exchange,提问作者hdmicable
相关产品推荐
相关产品推荐

