C++中SO_ATTACH_REUSEPORT_CBPF绑定UDP套接字时BPF程序报错
SO_ATTACH_REUSEPORT_CBPF绑定UDP套接字时BPF程序报错原因分析
在C++环境下使用SO_ATTACH_REUSEPORT_CBPF将以下BPF程序绑定到UDP套接字时会报错:
struct sock_filter code[] = { {BPF_LD | BPF_MEM, 0, 0, 0x00000000}, // load memory to accumulator //{BPF_ALU | BPF_ADD, 0, 0, 0x00000001}, // add 1 //{BPF_ALU | BPF_MOD, 0, 0, 0x00000003}, //module 3 //{BPF_ST , 0, 0, 0x00000000}, // save in scratch memory //{BPF_RET | BPF_A, 0, 0, 0x00000000}, // return value in accumulator };
但修改为仅包含返回指令的BPF程序后,代码可正常运行:
struct sock_filter code[] = { {BPF_RET, 0, 0, 0x00000000} };
第一段BPF程序存在两个核心问题:
缺少强制要求的返回指令:所有BPF程序必须以
BPF_RET指令结尾,用于向内核返回一个有效值(对于REUSEPORT_CBPF场景,返回值用于选择对应的UDP套接字)。你第一段代码中所有返回相关的指令都被注释掉了,程序没有合法的终止逻辑,内核在验证BPF程序时会直接判定为非法,拒绝加载。内存加载指令的上下文非法:你使用的
BPF_LD | BPF_MEM指令尝试从0x00000000地址加载数据到累加器,但REUSEPORT_CBPF的BPF程序只能访问内核预定义的上下文数据(比如UDP包的源端口、目的端口等),不能直接访问任意内存地址。这个无效的内存访问会触发内核的BPF程序验证失败,导致附加操作报错。
第二段程序仅包含BPF_RET指令,既满足了BPF程序必须有终止点的要求,返回值0也是合法的套接字选择索引(对应REUSEPORT组中的第一个套接字),因此可以通过内核验证并成功附加到UDP套接字。
内容的提问来源于stack exchange,提问作者Upendra Kumar
相关产品推荐
相关产品推荐

