标准库安全公告

2019 年 5 月 13 日 · Rust 核心团队

这是官方安全公告的交叉发布。官方帖子还包含使用我们的 PGP 密钥签名的版本。

此漏洞的 CVE 编号为 CVE-2019-12083


Rust 团队最近收到通知,标准库中手动实现的 Error::type_id 函数与其 Error::downcast 系列函数之间的交互存在安全漏洞。如果您的代码没有手动实现 Error::type_id,则不受影响。

概述

标准库中的 Error::type_id 函数在 2019 年 4 月 11 日发布的 1.34.0 版本中被稳定化。此函数允许获取底层错误类型的具体 TypeId,以便向下转型回原始类型。此函数在标准库中有一个默认实现,但也可以被下游 crate 覆盖。例如,在 Rust 1.34.0 和 Rust 1.34.1 上目前允许以下操作

struct MyType;

impl Error for MyType {
    fn type_id(&self) -> TypeId {
        // Enable safe casting to `String` by accident.
        TypeId::of::<String>()
    }
}

当与 Error::downcast* 系列方法结合使用时,这可能导致将一个类型安全地转换为错误的类型,从而引发越界读写等安全问题。

在 1.34.0 版本发布之前,此函数不稳定,无法在稳定版 Rust 中实现或调用。

受影响的版本

Error::type_id 函数首次在 2019 年 4 月 11 日发布的 Rust 1.34.0 中稳定化。2019 年 4 月 25 日发布的 Rust 1.34.1 也受到影响。自 1.0.0 版本以来,Error::type_id 函数一直存在(不稳定),这意味着使用 nightly 版本编译的代码可能随时受到影响。

缓解措施

此错误的即时缓解措施是删除手动实现的 Error::type_id,转而继承默认实现,从安全角度来看,默认实现是正确的。Error::type_id 的本意不是返回其他类型的 TypeId 实例。

对于长期缓解措施,我们将取消此函数的稳定化。对于调用 Error::type_id 的用户和覆盖 Error::type_id 的用户来说,这很不幸是一个破坏性更改。对于覆盖它的用户来说,很可能存在内存不安全问题,但调用 Error::type_id 的用户自上次 1.34.0 版本发布以来,在稳定版上只使用了几周,因此认为其影响不会太大,可以克服。

我们将于 2019 年 5 月 14 日(明天)发布 1.34.2 小版本,该版本将回滚 #58048 并取消 Error::type_id 函数的稳定化。即将发布的 1.35.0 版本以及 beta/nightly 通道也将全部更新并取消稳定化。

Error::type_id API 的最终命运尚未确定,它是 #60784 的议题。目前除了取消稳定化之外没有其他计划,因此 nightly 代码可能继续存在此问题。我们希望尽快在标准库中彻底解决此问题。

事件时间线

  • 2019 年 5 月 9 日星期四下午 14:07 - 向 security@rust-lang.org 报告 Bug
  • 2019 年 5 月 9 日星期四下午 15:10 - Alex 回应,确认 Bug
  • 2019 年 5 月 10 日星期五 - 制定并实施缓解计划
  • 2019 年 5 月 13 日星期一 - GitHub 上发布了针对 stable/beta/master 分支的 PR
  • 2019 年 5 月 13 日星期一 - 安全邮件列表获知此问题
  • (计划) 2019 年 5 月 14 日星期二 - Rust 1.34.2 发布,包含此问题的修复

致谢

感谢 Sean McArthur 发现此 Bug 并根据我们的安全策略向我们报告。