外部 Rust crate 的审核流程

因为需要审核,所以在这里?直接跳转到流程审核指南部分。

Rust 的外部库(也称为 crate)生态系统,是使用 Rust 语言的巨大优势。对于任何规模的团队来说,这个现有代码正文都可以成为强力倍增器,从而加速并降低风险。

同时,与所有代码一样,外部代码也存在风险。我们应该使用外部 crate,但要明智地使用它们!本文档介绍了如何在了解并最大限度地降低风险的同时最大限度地获益。

背景

在编写代码时,我们的树中有大约 100 万行外部 Rust 代码,因此对新 crate 进行代码审核以及对现有 crate 的更新需要进行大量的工作。为了应对目前代码库中 Rust 的庞大规模,我们必须让所有使用 Rust 的团队都能够审核团队所依赖的 crate。

同时,对于如何审核外部代码也不确定。 对外部代码的审核与第一方代码审核不同,而且业界的规范并不成熟。事实上,许多小型组织根本不执行外部代码审核,而是完全依赖于其他质量信号。

对于像 Fuchsia 这样的项目,我们无法容忍此类风险,并且必须审核我们用于交付产品的代码。同时,我们应该专注于最大限度地提升收益,同时最大限度地减少进程开销。

原则

根据风险分配审核工作

时间和精力有限。确定外部代码可能引入的最大风险,并专注于最大限度地降低这些风险。将这些风险与编写新实现的风险进行比较。

考虑未来的费用和收益

不局限于当下,当下便捷的捷径,日后可能会成为大问题。现在,解决更普遍的问题会在项目的整个生命周期中带来重复的益处。

谨慎应对意外情况

请注意,我们需要多次清除令人困惑的一段代码或它的 API。

没有默认结果

所有这些原则既适用于使用外部代码的决定,也适用于我们自行实现代码的决定。

回馈

开源库可能是该项目的一大好处。审核这些评价时,应确保项目外的人员能够轻松看懂这些评价的详细信息。

流程

审核第三方代码对于涉及到的各方来说可能非常耗时。请务必遵循请求和执行第三方审核的流程,以尽可能减少开销和重复工作量。

添加或更新外部 crate

当您添加或更新外部 crate 且需要他人审核您的更改时,请执行以下操作:

  1. 请按照外部 Rust crate 文档操作,将 crate 添加到树中。先不要将更改上传到 Gerrit。
  2. 如果有任何新的 crate,包括新版本的现有 crate 中的依赖项或对许可的更改,请为它们请求 OSRB 批准
  3. 任何新 crate 获得 OSRB 批准后,将更改上传到 Gerrit。 请务必执行以下操作:
    • 在提交消息中注明 OSRB 审批 bug。
    • 尽可能将第一方代码更改与外部代码更改分开。
    • 如果 crate 需要更新多个传递依赖项,请考虑使用 cargo update 将传递更新批量分为一个或多个批次,以减小 CL 大小。为了减少审核开销,您可以使用 cargo 的清单修补功能,将未在我们支持的平台上使用的依赖项替换为空 crate。
  4. 向 CL 添加审核人员。任何人(包括您在内!)都可以查看,但前提是他们了解本部分和以下准则。
    • 您可以通过在 Fuchsia Discord 的 #rust 频道或可以找到 Fuchsia rustaceans 的其他聊天室中提问,找到评价者。
    • 如果审核需要特定领域的专业知识(例如不安全的代码),请寻找具备该专业知识的审核人员。
    • 确保审核者知道需要审核哪些 crate。您可以将 crate 分配给各个审核者,这有助于处理大型 CL。
  5. 所有代码经过审核后,请添加其中一个 rust_crates OWNERS 以进行最终审批。1 其工作是确保正确遵循该流程,并且应在 CL 注释中明确提供支持。积极主动地将有助于确保快速获得批准。

查看外部 crate

当他人申请审核时,请务必:

  1. 根据审核指南查看代码,运用您的最佳判断并在必要时寻求外部帮助。
  2. 对代码添加备注,说明您查看了哪个 crate。记录您对审核的任何问题和注意事项。请注意内嵌显示的任何意外行为或 bug。一般来说,请注意所有风险(即使您认为这些风险不应阻止合并)。
    • 在 CL 级注释的第一行,说出您查看过的 crate 和版本。
    • 如果您在审核中发现任何注意事项或风险,请使用星号。 您可以缩写为“all crate”或“all crate”),以便 OWNERS 在做出最终批准之前快速浏览评论。
  3. 如果代码看起来可以接受合并,请添加“代码审核 +1”。如果您发现严重 bug 或其他危险信号,请添加“代码审核 -1”,并且可以选择性地建议解决方法,例如:
    • 在合并之前修补上游 crate。
    • 关闭 CL 并寻找替代方案。
    • 如果违规代码所在的依赖项未在 Fuchsia 支持的平台上使用,我们可以使用 cargo 的清单修补功能,将 crate 替换为空的 crate。

批准外部添加或更新操作 (OWNERS)

  1. 查找符合 CL 上的审核指南的证据:
    • 查看添加或更新外部 crate 的流程,确保遵循该流程。
    • 尽可能在 CL 上添加注释,而不是进行非正式沟通,因为注释会留下审核跟踪记录。
    • 如果缺少证据,请让 CL 所有者完成审核流程,并让他们参阅此文档。
  2. 审核审核人员注明的所有风险:
    • 根据需要请求澄清说明。
    • 提及任何应该阻止合并或需要进一步讨论的问题。添加了“代码审核 -2”,以确保在这些问题得到解决之前不会合并 CL。
  3. 在正确遵循相应准则之后,可以接受任何风险,并且您愿意合并,然后添加“代码审核 +2”。

查看准则

外部 crate 审核最多涉及四个主要部分:

  • 架构审核可在更高层面上评估外部代码,旨在发现“明显”问题。
  • 质量审核可以进一步审查新引入的 crate。
  • 代码审核侧重于验证代码的正确性。
  • OSRB 审批可确保我们添加的代码符合 Fuchsia 的许可政策。OSRB 审批是一个独立的流程,必须完成该流程才能上传引入外部代码的变更列表。

需要哪些组件取决于更改的性质:

宝箱行动 需要进行架构审核 需要进行质量审核 需要审核代码 需要进行 OSRB 审核
作为直接依赖项添加到 Cargo.toml 中
作为其他 crate 的间接依赖项使用
更新的版本 如果许可发生更改*

* 更新外部 crate 时,仅在许可发生更改(包括更改每个文件的许可)时才需要获得 OSRB 批准。

对 Fuchsia 代码使用的 crate 进行架构审核

架构审核旨在发现“明显”的问题,并且旨在进行轻量化。如果从架构角度不确定 crate 是否有意义,则应在 CL 中加以记录,以便作者和审核者做出最终判断。

添加要在树内使用的直接依赖项(即,它直接列在 Cargo.toml 清单中)时,新用户和评价者应提出以下问题:

  • 树中是否有类似的箱子可以作为替代?
  • 这个 crate 将引入多少个依赖项?它们有多大?
  • 检查和更新这些依赖项的成本是否与我们使用 crate 所获收益不成比例?
  • 这个 crate 在我们的架构背景下是否有意义?对于在 Fuchsia 目标上运行的代码:
    • 这在异步上下文中是否可用?(例如,该 API 是否需要阻塞语义?)
    • 此 crate 是否严重依赖于 POSIX 模拟?
  • 此 crate 是否具有包含充足文档的合理 API?
    • 如果 API 简单且不言自明,只需提供少量文档即可。
    • 如果 API 包含复杂的抽象,缺少文档会产生费用。
    • 如果 API 具有未记录的不变体,并且代码特别不安全,则风险很高。

请注意,这些问题不适用于我们不会直接使用的传递依赖项。在将现有的传递依赖项提升为直接依赖项时,我们应该询问并回答这些问题。

对新供应商的 crate 进行质量审核

除了下面的审核指南之外,审核者还应额外考虑新的 crate,无论是由我们直接使用,还是用作其他 crate 的依赖项。

确保 crate 已获得 OSRB 批准

展望未来。

想想我们与这个宝箱的关系可能会随着时间而改变。

是否值得审核此 crate 及其依赖项,是否值得使用其 API 带来好处?

您还需要考虑审核未来更新的成本。

此 crate 可能适用于其他哪些情况?

对于每种新的使用情形,我们都不会重新审核其实施情况。如果您认为 crate 只能用于特定平台,或者您考虑到该假设,请在 Cargo.toml 中的注释中加以说明。

有些 crate 并不适用于所有可能的上下文,例如在特定平台上。如果存在任何使用 crate 不安全的上下文,我们必须修改 build,以防止在这些上下文中使用 crate。否则,无法导入 crate。

如果维护人员抛弃 crate,会出现什么情况?

我们愿意自己复刻和维护吗?

注意质量信号。

所有这些质量信号都可以通过 crates.io 或通常链接到的源代码库找到。

一阶信号为我们提供了一个直接证明箱子质量的证据:

  • 代码审核
    • 代码审核是最基本的一级信号。虽然代码审核始终是必须进行的,但这几乎并非完全详尽。
  • 测试
    • 没有在箱子中进行测试是一个危险信号。并非所有测试都需要进行审核,但应抽查一些测试,确定是否有有意义的语义检查和良好的覆盖率。此外,请检查 crate 的测试是在其 CI 中通过,还是通过 cargo test 通过本地检出。可靠的测试是一个很好的信号。

二阶信号提供间接证据,用于证明 crate 的质量,并且应该用作支持证据。使用 crate 时,缺少二阶信号不应失去资格。相反,这些信号应有助于填补信心缺口,并在不确定的时刻帮助人们找到平衡:

  • 多个维护者
  • 知名作家
  • 常用的反向依赖项
    • 这些依赖项会列在 crates.io 上的“Dependents”(依赖项)下。
  • 代码库和问题跟踪器中的活动

针对所有外部代码的代码审核

查看外部代码时,无论是新 crate 还是对现有 crate 的更新:

发现风险

外部代码中存在的常见风险包括:

  • unsafe 代码

    • 请仅在必要时使用不安全的代码。应易于跟踪和/或记录其不变量及其保留方式。不安全的 API 应该很少见,并且必须始终记录调用方需要支持的不变量。2

      外部 crate 中的不安全代码必须由不安全的 Rust 代码审核人员进行审核。如需了解详情,请参阅“请求不安全的代码审核”

  • 需要专业领域专业知识才能理解的代码

    • 如果可能,请咨询网域专家查看此代码。例如,不安全的低级别原子和并发、加密以及网络协议实现。
  • 要在关键路径中使用的代码

    • 这包括安全关键型路径(如加密)以及性能关键型路径。请特别注意该代码,以确保它不会破坏关键路径。
  • 代码过于复杂

    • 惯用的 Rust 利用适当的抽象级别,尽可能使用类型系统来管理不变量。如果代码难以遵循,让您无法确信这些不变的管理方式是否得到妥善管理,则可能是因为代码质量低下且包含可避免的 bug。

与往常一样,请务必注意我们的替代方案。假设我们需要此功能,如果我们自行编写代码,是否会面临相同的风险?这样做实际上是否会产生更好的结果,是否值得花费精力编写和维护这些代码?

验证信息是否正确,但切勿过度。

在理想情况下,我们能够正式验证我们使用的所有外部代码。但这通常不现实,因此我们需要充分利用我们的时间和精力来增强信心,同时确保流程继续进行。请尽最大努力:

  • 验证实现方式是否合理
    • 给定函数签名、特征等。
  • 寻找意料之外的现象
    • 请务必记下 CL 注释中找到的所有内容(最好内嵌在令人惊讶的代码中)。
  • 将注意力集中在手头的代码中
    • 您可以假定其他函数会如您所愿,因为您最终会回顾这些函数。您没有必要跟踪整个函数调用图,如果跟踪,通常是一个不好的迹象。请运用您的最佳判断来集中精力。
  • 确保 build.rs 更改已反映在我们的 build 中
    • build.rs 脚本不在 build 中运行,但在供应商 crate 时需要进行转换。cargo-gnaw 对此仅提供有限支持,但它无法捕获全部内容。查看这些更改,并验证与我们的 build 相关的所有更改都会反映在我们的构建规则中。如果您对审核内容不满意,可以请 CL 所有者为其寻找其他审核者。

跳过不相关的内容。

您无需查看以下内容:

  • 代码样式
  • 已审核的未更改代码
  • 单独的测试用例和基准
  • 我们确信这些平台上的平台专用代码永远不会用到3
  • 对充分了解 API Surface 和实现没什么直接帮助的文档进行审查

如前所述,在评估新 crate 的质量时,其中的部分指标仍然适用。

请求不安全的代码审核

为了确保 Fuchsia 是基于可靠的外部代码构建的,我们会对外部 crate 中的所有不安全代码进行全面审核。不安全的代码通常需要特殊专业知识来进行审核,因此当 crate 添加或更新不安全的代码时,它必须获得不安全审核者的批准。

如需请求不安全的代码审核,请执行以下操作:

  1. 使用“Unsafe review for external crate”模板提交 bug,并填写相应内容:
    • 经过修改的 crate,是标题中的直接依赖项。
    • CL 的审核链接。
    • CL 的上传日期。
    • 发生更改的总行数(位于 Gerrit 中的文件列表底部)。
    • 已添加或更新的组成 crate。
    • 请参考下面的示例
  2. 将“Fuchsia Rust Unsafe Reviews fuchsia-rust-unsafe-reviews@google.com”添加为 CL 的审核者。系统会随机选择审核人员,并将其分配给您的 CL。

如果您的审核具有时效性,请提高 bug 的优先级,并发表评论来说明您的情况。

展开


  1. 在不久的将来,我们预计会在审核时为 Rust 第三方 crate 分配更精细的所有权,从而让更多人管理 crate 升级。

  2. 另请参阅我们针对第一方代码中的不安全准则设定的准则。

  3. 我们支持 Fuchsia、Linux 和 Mac,并且应该会在某个时间支持 Windows。我们的部分 Rust 代码也会针对 wasm 目标进行编译。