跳转到主要内容

扫描Python wheels以查找abi3违规和不一致

项目描述

abi3audit

Tests PyPI version Packaging status

阅读关于我们如何使用abi3audit找到错误的Trail of Bits博客文章!

abi3audit扫描Python扩展以查找abi3违规和不一致。

它可以扫描单个(未打包)共享对象、打包的wheels或整个包版本历史。

An animated demonstration of abi3audit in action

该项目部分由Trail of Bits维护。这不是Trail of Bits的官方产品。

索引

动机

CPython(Python的参考实现)定义了一个稳定的API和相应的ABI("abi3")。原则上,任何CPython扩展都可以针对此API/ABI构建,并且将与未来CPython的较小版本保持向前兼容。换句话说:如果您针对Python 3.5的稳定ABI构建,则您的扩展无需修改即可在Python 3.9上运行。

稳定的ABI简化了CPython扩展的打包,因为打包者只需要构建一个针对最低支持的Python版本的abi3 wheel。

为了表示Python wheel包含abi3兼容的扩展,Python打包生态系统使用abi3 wheel标签,例如。

pyrage-1.0.1-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl

不幸的是,在安装或运行时对Python扩展中的abi3合规性没有实际执行:标记为abi3的wheel(或独立共享对象)被认为具有abi3属性,但没有任何方式验证。

更糟糕的是,控制wheel标记的标志(--py-limited-api)与实际将Python扩展锁定到特定abi3版本的构建宏(Py_LIMITED_API)之间没有正式的联系。

结果:很容易编译出错误版本的abi3的Python扩展,或者在没有实际将其编译为abi3-兼容的情况下将Python wheel标记为abi3

这具有严重的安全和可靠性影响:CPython ABI的非稳定部分可能在较小版本之间发生变化,导致崩溃、不可预测的行为,或者当Python扩展错误地假设函数的参数或结构的布局时,可能会造成可利用的内存损坏。

安装

abi3audit可通过pip获取

pip install abi3audit

使用

作为独立程序运行abi3audit,或通过python -m abi3audit

abi3audit --help
python -m abi3audit --help

顶级

usage: abi3audit [-h] [--debug] [-v] [-R] [-o OUTPUT] [-s] [-S]
                 [--assume-minimum-abi3 ASSUME_MINIMUM_ABI3]
                 SPEC [SPEC ...]

Scans Python extensions for abi3 violations and inconsistencies

positional arguments:
  SPEC                  the files or other dependency specs to scan

options:
  -h, --help            show this help message and exit
  --debug               emit debug statements; this setting also overrides
                        `ABI3AUDIT_LOGLEVEL` and is equivalent to setting it
                        to `debug`
  -v, --verbose         give more output, including pretty-printed results for
                        each audit step
  -R, --report          generate a JSON report; uses --output
  -o OUTPUT, --output OUTPUT
                        the path to write the JSON report to (default: stdout)
  -s, --summary         always output a summary even if there are no
                        violations/ABI version mismatches
  -S, --strict          fail the entire audit if an individual audit step
                        fails
  --assume-minimum-abi3 ASSUME_MINIMUM_ABI3
                        assumed abi3 version (3.x, with x>=2) if it cannot be
                        detected

示例

审计单个共享对象、wheel或PyPI包

# audit a local copy of an abi3 extension
abi3audit procmaps.abi3.so

# audit a local copy of an abi3 wheel
abi3audit procmaps-0.5.0-cp36-abi3-manylinux2010_x86_64.whl

# audit every abi3 wheel for the package 'procmaps' on PyPI
abi3audit procmaps

在审计时显示更多信息(格式化的表格和单个违规项)

abi3audit procmaps --verbose

yields

[17:59:46] 👎 procmaps:
           procmaps-0.5.0-cp36-abi3-manylinux2010_x86_64.whl: procmaps.abi3.so
           uses the Python 3.10 ABI, but is tagged for the Python 3.6 ABI
           ┏━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
           ┃ Symbol                  ┃ Version ┃
           ┡━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
           │ PyUnicode_AsUTF8AndSize │ 3.10    │
           └─────────────────────────┴─────────┘
[17:59:47] 💁 procmaps: 2 extensions scanned; 1 ABI version mismatches and 0
           ABI violations found

为每个输入生成JSON报告

abi3audit procmaps --report | python -m json.tool

yields

{
  "specs": {
    "procmaps": {
      "kind": "package",
      "package": {
        "procmaps-0.5.0-cp36-abi3-manylinux2010_x86_64.whl": [
          {
            "name": "procmaps.abi3.so",
            "result": {
              "is_abi3": true,
              "is_abi3_baseline_compatible": false,
              "baseline": "3.6",
              "computed": "3.10",
              "non_abi3_symbols": [],
              "future_abi3_objects": {
                "PyUnicode_AsUTF8AndSize": "3.10"
              }
            }
          }
        ],
        "procmaps-0.6.1-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl": [
          {
            "name": "procmaps.abi3.so",
            "result": {
              "is_abi3": true,
              "is_abi3_baseline_compatible": true,
              "baseline": "3.7",
              "computed": "3.7",
              "non_abi3_symbols": [],
              "future_abi3_objects": {}
            }
          }
        ]
      }
    }
  }
}

限制

abi3audit是一个尽力而为的工具,具有与auditwheel相同的某些限制。特别是

  • abi3audit无法检查动态的abi3违规,例如扩展在运行时调用dlsym(3)来调用非abi3函数。

  • abi3audit可以确认abi3兼容符号的存在,但没有abi3-不兼容符号的详尽列表。相反,它通过寻找不在abi3兼容性列表中的以Py__Py_开头的符号来查找违规。这不太可能导致误报,但如果扩展错误地使用了这些保留的前缀,则可能发生误报。

  • 当审计一个“裸”共享对象(例如foo.abi3.so)时,abi3audit不能假设关于最小预期abi3版本的任何内容。相反,它默认为最低已知的abi3版本(abi3-cp32),并在版本不匹配时发出警告(例如,仅在3.6中稳定的符号)。这可能导致误报,因此建议用户审计整个wheel或包(因为它们包含足够的元数据)。

  • abi3audit 在考虑符号稳定化版本时,考虑的是稳定化版本,而不是引入版本。换句话说:当 abi3-cp36 扩展包含在 3.7 中稳定的函数时,即使该函数在 3.6 中引入,abi3audit 也会产生警告。这 不是 假阳性(这是一个 ABI 版本不匹配),但它通常 不是 错误的来源。

  • abi3audit 检查每个扩展的“本地”和“外部”符号,对于支持这两种格式的格式。这样做是为了捕获内联的符号,例如 _Py_DECREF。然而,如果扩展的符号表已被剥离,这些可能被遗漏。

许可

abi3audit 使用 MIT 许可证授权。

abi3audit 包含从 Kaitai Struct 项目提供的定义生成的 ASN.1 和 Mach-O 解析器。这些供应商解析器由 Kaitai Struct 作者根据 MIT 许可证授权。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪一个,请了解更多关于 安装包 的信息。

源分布

abi3audit-0.0.17.tar.gz (30.0 kB 查看散列值)

上传时间

构建分布

abi3audit-0.0.17-py3-none-any.whl (30.8 kB 查看散列值)

上传时间 Python 3

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页