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

eBPF Verifier报R2内存范围错误及编译位移指令疑问

eBPF Verifier报错分析与位移指令解读

一、位移指令r2 <<= 0x20的作用

你看到的r2 <<= 0x20(左移32位)加后续的r2 s>>= 0x20(算术右移32位),是LLVM编译器生成的有符号整数扩展代码:

  • 原代码中i是32位有符号int,加载到64位eBPF寄存器后,高32位是未定义的(因为是按u32类型从内存读取)。
  • 左移32位会把低32位的符号位推到64位寄存器的符号位,再通过算术右移32位,把32位有符号数完整扩展为64位有符号数,保证i的正负值在64位寄存器中正确表示,满足后续if(i > 0)的有符号比较逻辑。

二、Verifier报错"R2 max value is outside of the allowed memory range"的原因与解决

报错根源

看Verifier日志核心提示:

invalid access to map value, value_size=20 off=76 size=4
R2 max value is outside of the allowed memory range

数组a是int[5],总大小为20字节(5*4),但你的边界检查逻辑错误:

  • 代码里写的i < sizeof(a),sizeof(a)返回的是数组总字节数20,而非元素个数5。这意味着i的合法范围被错误放宽到0-19。
  • 当i=19时,a[i]的内存偏移量是19*4=76,远超出数组20字节的总大小,触发Verifier的内存越界检查。

代码修复

把边界条件从检查字节数改为检查元素个数,用ARRAY_SIZE(a)或者直接写5:

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

int a[5], b=3, i=2;

SEC("xdp")
int hello(void *ctx){
    // 检查索引是否在数组元素范围内,而非总字节数
    if(i > 0 && i < ARRAY_SIZE(a)){
        a[i] = b;
    }
    return XDP_PASS;
}

char _license[] SEC("license") = "GPL";

修复逻辑验证

修复后,i的最大值被限制为4,对应的内存偏移量是4*4=16,加上数组基地址后,访问范围刚好是0-19字节(数组总大小20),Verifier会认可这个合法边界,不再抛出越界错误。

补充:Verifier日志关键信息解读

  • R1_w=scalar(id=1,umax=19,var_off=(0x0; 0x1f)):寄存器R1存储的i最大值为19,这是错误的i < sizeof(a)导致的。
  • R1_w=scalar(umax=76,var_off=(0x0; 0x7c)):i*4后的最大值为76,超过数组20字节的总大小,触发越界检查。

内容的提问来源于stack exchange,提问作者Akash Cherukuri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 00:14:55