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