CPython 编译器加固

今年夏天,作者参与了 Python 软件基金会的 CPython 项目,专注于实现开源软件基金会建议的强化编译器选项。

  • 项目背景与起源:2023 年底,CPython 核心开发者注意到 OpenSSF 的内存安全特别兴趣小组正在开发通过启用编译器和链接器选项来提供安全 C 和 C++代码的指南。随后在 CPython 的 GitHub 仓库中提出了一个问题,建议 CPython 考虑 OpenSSF 内存安全 SIG 的建议并将其应用于构建过程。该问题被提议为 Google Summer of Code 项目,作者申请并被选为贡献者。
  • 初始选项选择:OpenSSF 指南提供了一组初始的编译器选项,作者最初在 Fedora 40 x86_64 机器上进行测试,包括 -O2 -Wall -Wformat -Wformat=2 -Wconversion -Wimplicit-fallthrough -Werror=format-security -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS -fstrict-flex-arrays=3 -fstack-clash-protection -fstack-protector-strong -Wl,-z,nodlopen -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now 等。但在测试过程中发现 nodlopen 选项不适合 CPython 项目,于是修改了配置,去除了 nodlopen-fstrict-flex-arrays=3 等选项。
  • 基准测试:作者使用 pyperformance 进行基准测试,发现本地测试结果不稳定,最终依靠 faster-cpython 的专用实验室获得可靠的基准测试结果。在 faster-cpython 上的基准测试显示,所选选项集对性能影响不大。
  • 第一个 PR:第一个 PR 的目的是引入不生成警告的警告选项和不影响性能的运行时保护选项,包括 -Wimplicit-fallthrough-Wtrampolines-fstack-protector-strong-fno-strict-overflow 等。但合并后出现了问题,如 gcc 在 macOS 上是 clang 的包装器,导致构建失败,以及 clang 对某些未注释的 fallthrough 情况发出警告等。这促使创建了平台特定的警告跟踪工具。
  • 警告工具:在 CPython CI 工具链中,已有用于文档构建的警告检查,作者在此基础上开发了用于编译器警告检查的工具,该工具应具备跟踪回归和改进、选择工作流失败模式以及识别忽略警告的文件等功能。工具通过在 GitHub Actions 中集成实现,并使用 act 在本地进行测试。
  • 引入工具:计划逐步引入工具,最初将其集成到 CPython CI 中,不更改构建标志,然后引入生成警告的编译器选项,并更新警告忽略文件,启用 --fail-on-regression--fail-on-improvement。但引入新更新后,工作流在 GitHub 上运行时出现了问题,如出现新的意外警告和改进,以及文件系统的竞争条件等。
  • 持续工作

    • 处理现有警告:一旦生成警告的编译器选项和正确的忽略配置合并,将开始处理现有代码库中的数千个警告,开发分析和修复警告的流程,或记录不处理的原因。
    • 工具改进:讨论了改进工具的方法,如能够完全忽略整个文件或目录,以及按警告类型和文件忽略警告等。

作者感谢了 Seth Larson、Hugo van Kemenade、Donghee Na 和 Michael Droettboom 等人在项目中的帮助和支持。

阅读 14
0 条评论