7 个版本

0.2.1 2022 年 9 月 22 日
0.2.0 2022 年 9 月 22 日
0.1.4 2021 年 12 月 8 日
0.1.3 2021 年 8 月 26 日
0.1.1 2021 年 2 月 23 日

#363 in 测试

每月 33 次下载

AGPL-3.0

55KB
1K SLoC

亲铁素

CI Crates.io

亲铁素可以找到您的 Rust 代码库中“最不安全”的函数,以便您可以对它们进行模糊测试或完全重构。

它检查代码库中每个函数的调用图,估计在评估该函数时调用了多少 unsafe 表达式,然后按此值生成一个列表。以下是亲铁素输出格式的样子

Badness  Function
    092  <myProject::myThing as my_project::myThing>::tempt_fate
    064  <myProject::myOtherThing::whatever as my_project::myThing>::defy_death
    [...]

函数的“坏度”简单来说是评估该函数时评估了多少 unsafe 表达式的近似值。例如,使用 * 标记 unsafe 函数,假设您的函数 f 调用了函数 g*h。此外,h 调用了 i*。然后 f 的坏度是 2。坏度高的函数有很多机会出现内存不安全。

安装

亲铁素可通过 crates.io 获得,并可以使用 cargo 安装

cargo install siderophile

运行该步骤时,您可能会看到来自 llvm-sys crate 的错误

error: No suitable version of LLVM was found system-wide or pointed
              to by LLVM_SYS_140_PREFIX.

              Consider using `llvmenv` to compile an appropriate copy of LLVM, and
              refer to the llvm-sys documentation for more information.

              llvm-sys: https://crates.io/crates/llvm-sys
              llvmenv: https://crates.io/crates/llvmenv
   --> /Users/william/.cargo/registry/src/github.com-1ecc6299db9ec823/llvm-sys-140.0.2/src/lib.rs:487:1
    |
487 | / std::compile_error!(concat!(
488 | |     "No suitable version of LLVM was found system-wide or pointed
489 | |        to by LLVM_SYS_",
490 | |     env!("CARGO_PKG_VERSION_MAJOR"),
...   |
497 | |        llvmenv: https://crates.io/crates/llvmenv"
498 | | ));
    | |__^

error: could not compile `llvm-sys` due to previous error

这表示构建无法自动找到要链接的 LLVM 的副本。

您可以通过设置 LLVM_SYS_140_PREFIX 来修复它。例如,对于使用 Homebrew 的 macOS 上的 LLVM,您可能这样做

LLVM_SYS_140_PREFIX=$(brew --prefix)/opt/llvm/ cargo install siderophile

从源代码构建和安装

或者,如果您想从源代码构建

git clone https://github.com/trailofbits/siderophile && cd siderophile

# TIP: include --release for a release build
cargo build

# optionally: install the built binary to cargo's default bin path
cargo install --path .

如何使用

请确保您已遵循上述步骤,然后执行以下操作

  1. cd 进入您要分析的项目根目录

  2. 运行 siderophile --crate-name CRATENAME,其中 CRATENAME 是您要分析的项目名称

函数将被写入到 stdout,按照其严重程度排序。

工作原理

Siderophile 扩展了 cargo-geiger,其目标是找到项目级别的安全问题。

首先,通过让 cargo 输出项目的位码,然后解析它以生成调用图并将名称去混淆为可以与源代码匹配的内容来创建调用图。

接下来,Siderophile 找到当前项目的所有源文件,找到源文件中的每个 Rust 文件,并使用 syn 项目逐个解析每个文件。将递归地搜索函数、特质声明、特质实现和子模块中的不安全性。Siderophile 将输出这些对象的路径,以及它们被发现的语法块的类型。从这一步收到的列表包含项目每个依赖项中的每个不安全块,无论其是否被使用。为了缩小范围,Siderophile 需要将其列表与项目的调用图中的节点进行比较。

使用第一步生成的调用图,Siderophile 检查输出中哪些元素实际上是从待查项目执行的。这一步(在 src/callgraph_matching 中实现)并不能保证找到所有内容,但它在手动搜索中已经显示出良好的结果。它也不是不会出现误报,尽管目前还没有发现。已发现的不安全节点的标签被用作最后一步的输入。

最后一步是跟踪调用图中的这些不安全节点。对于列表中的每个节点,Siderophile 将找到调用图中每个上游节点,并将它们的严重程度增加一级,从而指示它们在执行过程中某个时刻使用了不安全性。在此过程结束时,所有非零严重程度的节点都将按严重程度降序打印出来。

限制

Siderophile 不能保证捕获项目中所有依赖项中的不安全性。

由于仅在源代码级别进行标记,Siderophile 没有能力检查宏或解析动态分派的方法。因此,不应使用此工具来“证明”项目不包含任何不安全性。

调试

要从 siderophile 获取调试输出,请设置环境变量 RUST_LOGsiderophile=XXX,其中 XXX 可以是 infodebugtrace

感谢

感谢 cargo-geigerrust-praezi 提供的最佳实践。此项目主要归功于他们的工作。

许可证

Siderophile 根据 AGPLv3 许可证许可和分发。

如果您正在寻找对条款的例外情况,请联系我们:联系我们

依赖项

~52MB
~1M SLoC