Page 11 - 《软件学报》2024年第6期
P. 11
陈金宝 等: DBI-Go: 动态插桩定位 Go 二进制的非法内存引用 2587
行时崩溃产生的原因, 从而 Go 的 GC 的崩溃输出几乎不能提供有效的信息帮助开发者定位问题. 像前述的
issue#44614 从 Go1.14 便开始出现, 直至 Go1.17 发布前才被修复, 影响了 Go1.14.x、Go1.15.x、Go1.16.x 这 3 个
大版本.
年份 issue 号 版本 备注
2022 54247 go1.17 堆指向栈的问题
2022 53289 go1.18 堆指向栈的问题
2022 51481 go1.18 堆指向栈的问题
2022 52008 go1.15 堆指向栈的问题
2021 47415 go1.16 CGO 相关逃逸问题
2021 49755 go1.16 堆指向栈的问题
2021 47276 go1.16 堆指向栈的问题
2021 44614 go1.14至1.16 堆指向栈的问题
2021 43818 go1.17 寄存器传参问题
2020 41635 go1.16 逃逸调试信息错误 5
2020 42944 go1.16 堆指向栈的问题
个使用动态二进制插桩方式分析
2019 31573 go1.13 逃逸带来的 runtime 问题 4
2019 32959 go1.13 逃逸带来的编译问题 issue 数量 3
2018 29000 go1.11至1.12 逃逸带来的 runtime 问题
2018 29353 go1.13 逃逸带来的 runtime 问题 2
2018 26987 go1.12 逃逸带来的 runtime 问题
2017 23045 go1.11 逃逸带来的 uintptr 问题 1
2017 2018 2019 2020 2021 2022
issue 链接: https://github.com/golang/go/issues/ 年份
图 1 社区中 Go 逃逸错误相关 issues (不完全统计) 图 2 社区中 Go 逃逸错误相关 issues 数量变化趋势
针对 Go 程序和/或 Go 语言编译器的漏洞检测, 目前多集中在对 Go 程序的并发、竞争检测方面 [17−19] , 与 Go
语言编译器的逃逸分析相关的研究屈指可数, 仅有 Wang 等人的工作 [20] 使得一些对象可以绕过 Go 语言编译器的
逃逸分析, 从而节省堆内存的使用. 目前尚无相关工作来寻找经 Go 语言编译器编译出的代码中的错误内存引用,
学术界对此的研究缺失. 同时, 目前 Go 官方对逃逸分析正确性的测试手段也较为有限, 难以辅助开发人员对逃逸
分析算法进行进一步的优化或重构.
为了有效检测编译器生成的代码是否存在可能引起运行时崩溃的非法内存引用, 在产品上线前就能及时发现
问题, 避免产品在实际生产环境中出现崩溃, 造成损失, 也为了辅助开发人员对内存优化相关算法, 如逃逸分析进
行优化和重构, 验证算法的正确性, 本文提出一种结合静态分析和动态插桩检测 Go 二进制中可能导致非法内存
引用的 store 指令的方法, 并基于 Pin [21] 实现了工具原型 DBI-Go, 它可以在不修改 Go 编译运行时系统的情况下对
Go 二进制程序进行检测, 具有较好的适用性. 该工具权衡静态分析和动态插桩, 并结合 Go 的语言特性, 大大减少
了误报率和插桩带来的额外开销.
本文的主要贡献点包括以下内容.
• 对 Go 二进制程序进行抽象, 并基于此抽象分析提出两条判定非法内存引用的判定规则. 非法内存引用由二
进制程序中将不当的地址通过 store 指令写入: (1) 将栈地址存入栈外; (2) 将较浅栈帧中的对象的地址存入较深栈帧.
• 提出了 DBI-Go——第 1 Go 二进制中潜在非法内存引用的工具. DBI- Go
可以将 Go 的二进制可执行文件与 Go 语义以及 Go 的运行时管理系统关联起来, 有着较低的误报率, 且在大多数
情况 (93.3%) 有不超过 2 倍的额外运行时开销. DBI-Go 还可以精准给出违例的发生位置, 帮助快速定位问题.
• 实验结果表明, DBI-Go 可以检测出 Go 社区中所有已知的逃逸相关 issue, 有着较高的漏洞覆盖率. 同时 DBI-
Go 还发现了一个目前 Go 社区未知的问题. 该问题已经在 golang-nuts 中得到 Go 官方维护人员的确认 (https://
groups.google.com/g/golang-nuts/c/YZVFzwnPixM), 并已向社区提交 issue 有待 Go 官方的进一步修复 (https://github.
com/golang/go/issues/61730).
• 对 DBI-Go 的实际应用还表明, 其可以辅助开发人员对 Go 逃逸分析算法进行优化和重构, 帮助找到新逃逸