You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重构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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:02:31