BPF加载报错unknown opcode 70:字符串匹配代码问题求助
问题:BCC中命令名过滤BPF代码加载触发unknown opcode 70错误
我尝试通过命令名过滤函数调用,使用以下代码(其中##REPLACE_comm##会由Python替换为具体命令名,双反斜杠是因为使用BCC框架),但加载时触发错误:
if(1){ char filter[TASK_COMM_LEN] = "##REPLACE_comm##"; char command[TASK_COMM_LEN]; bpf_get_current_comm(&command, sizeof(command)); for(u16 i = 0; i<=TASK_COMM_LEN; i++){ if(command[i] == '\\0' && filter[i] == '\\0'){ break; } if(command[i] == filter[i]){ continue; } return 0; } }
错误信息如下:
unknown opcode 70
HINT: The 'unknown opcode' can happen if you reference a global or static variable, or data in read-only section. For example, 'char *p = "hello"' will result in p referencing a read-only section, and 'char p[] = "hello"' will have "hello" stored on the stack.
我已确保变量分配在栈上而非仅使用指针,但问题仍存在,请问我忽略了什么?
问题分析与解决
- 栈上字符串初始化的BPF限制:虽然你用了栈数组
char filter[TASK_COMM_LEN] = "xxx"的写法,但BPF虚拟机并不支持直接在栈上用字符串常量初始化数组。这种写法在标准C中合法,但BPF验证器会将其判定为对只读数据段的引用,进而触发未知操作码错误。 - 循环边界越界:你的循环条件是
i<=TASK_COMM_LEN,而TASK_COMM_LEN通常为16(进程名最大长度,含末尾\0),数组下标从0开始,当i=TASK_COMM_LEN时会访问数组越界位置,这也可能触发验证器的额外检查。
解决方法
- 手动逐个字符初始化栈数组:替换直接用字符串常量初始化的方式,通过Python生成逐个字符赋值的代码。比如将
char filter[TASK_COMM_LEN] = "bash"替换为:char filter[TASK_COMM_LEN] = {0}; filter[0] = 'b'; filter[1] = 'a'; filter[2] = 's'; filter[3] = 'h'; - 修正循环边界:将循环条件改为
i < TASK_COMM_LEN,避免越界访问。 - 简化比较逻辑:使用BPF内置的
bpf_strncmp函数直接比较字符串,既简洁又能规避手动循环的错误:char filter[TASK_COMM_LEN] = {0}; // 通过Python生成逐个字符赋值代码 bpf_get_current_comm(&command, sizeof(command)); if (bpf_strncmp(command, filter, TASK_COMM_LEN) != 0) { return 0; }
内容的提问来源于stack exchange,提问作者johannes
相关产品推荐
相关产品推荐

