eBPF Talk: 3.18 kernel 里的 verifier 核心内容
文章目录
在 eBPF Talk: 3.18 kernel 里的 CFG 检查 里,我们学习了如何检查 bpf prog 的控制流程图(CFG,Control Flow Graph)是不是一个有向无环图(DAG,Directed Acyclic Graph)。在本文里,我们将学习 verifier 核心内容。
在该 commit 里,实现了对如下内容的检查:
- 无效的指令
- 未初始化的寄存器的访问
- 未初始化的栈的访问
- 非对齐的栈的访问
- 超出范围的栈的访问
- 非法的调用约定
- 指令编码不使用预留的属性
为了检查以上内容,还需要以下两个回调函数进行辅助:
bool (*is_valid_access)(int off, int size, enum bpf_access_type type):检查哪些ctx属性是可以访问的(ctx就是 bpf prog 的第一个参数)。const struct bpf_func_proto *(*get_func_proto)(enum bpf_func_id func_id):返回func_id对应的函数原型,用于检查函数调用的合法性。
推荐对该 commit 的内容进行阅读。
do_check() 函数
在 do_check() 函数里,遍历 bpf prog 的每一条指令,根据指令的类型进行不同的处理。
BPF_LDX、BPF_STX``、BPF_ST、BPF_LD:检查寄存器和栈的访问是否合法。BPF_JMP:检查BPF_CALL、BPF_JA、BPF_EXIT和其它有条件跳转指令等跳转指令的合法性。
小结
以上内容的检查的实现都比较琐碎,基本上是根据每条指令 case by case 地进行检查。以我浅薄的文字功底,只能抛砖引玉了。
文章作者 Leon Hwang
上次更新 2024-04-01