写点什么

Cloudflare 发现了 hyper HTTP/1 实现中的竞态条件问题并进行了修复

作者:Renato Losio
  • 2026-08-12
    北京
  • 本文字数:1398 字

    阅读完需:约 5 分钟

Cloudflare 最近记录了其开发团队如何发现并修复一个Rust常用HTTP库hyper中的罕见漏洞:该漏洞可能会在返回HTTP 200成功响应的情况下,悄然截断大型的 HTTP 响应。该问题已经存在多年,仅在特定的时序条件下才会触发,现在它已经在上游修复,这引发了 Rust 从业者对该事件及 Cloudflare 处理方式的讨论。

该漏洞是在 Cloudflare 的Cloudflare Images中重构 Workers Images 绑定时被发现的。上线后,尽管响应报告为成功,但是部分大型图像转换请求会间歇性返回被截断的数据。

在技术拆解中,团队说明了是如何逐步定位根因并列出修复路径的。Cloudflare 的产品经理Deanna Lam、高级系统工程师Diretnan DomnanMatt Lewis一同总结说:

我们花了六周时间追踪一个几乎不可见的漏洞,在 hyper 库中仅在特定条件下发生的竞态条件,影响了 Images 绑定如何将处理后的图像数据返回给客户端。最终,我们只用了四行代码就修复了它。

Rust的hyper库是一个实现 HTTP 协议的底层网络库,为许多高层 Rust Web 框架和应用所依赖的客户端与服务端提供了核心功能。该项目始于 2014 年,由 Sean McArthur 发起,采用宽松的 MIT 许可发布。

在客户开始报告图像被截断后,团队注意到响应返回了期望的 Content-Length 且状态为 HTTP 200,但在某些实例中只实际传输了 200 KB 而不是预期的 3.3MB,这使得截断源头难以识别。

团队通过构建可靠的复现用例、在不同 hyper 版本与环境中测试、对每个服务进行埋点,并使用分布式追踪逐步排除了各种可能性,最终将问题锁定到 Images 服务的 HTTP 响应路径。

应用层的追踪与日志并为显示错误,但低层内核系统调用跟踪(strace)显示 hyper 在缓冲的响应数据完全发送前就过早关闭了连接,确认了一个依赖时序的竞态条件。

Cloudflare 将问题追溯到了 hyper 的 HTTP/1 分发循环,它错误地忽略了未完成的缓冲刷新并过早关闭了连接,这导致在罕见时序下缓冲的响应数据丢失。为了修复该问题,团队添加了可确定性复现该竞态的测试,并修改了 hyper,确保在关闭连接前完成缓冲数据的刷新。Lam、Domnan 与 Lewis 补充说:

关键突破来自使用了内核级工具 strace,这是一层能记录套接字上实际发生了什么事情的手段。根本的漏洞存在于部分刷新与过早关闭之间的几毫秒窗口,这是在我们让系统变得更快后才出现的。

在 Reddit 上,Rust 编译器的贡献者 Martin Nordholts 对此发表了评论

这是异步 Rust 已知的设计缺陷。在同步 Rust 中,如果能通过编译,通常就能工作,而在异步 Rust 中,情况并非如此。一类导致此类问题的原因是静默取消(silent cancellation),本文就是此类漏洞可能带来问题的一个例子。

关于 Cloudflare 并未赞助 hyper 及其他重要的 Rust 基础库的维护者 Sean McArthur,Jim Fuller写到

一家年收入达 20 亿美元的公司撰写了精彩文章,却似乎并未直接支持那些对该公司收入至关重要的开发人员。

在一条热门的Hacker News讨论 中,有从业者将注意力放在 Rust 的代码质量上:

如果启用 Clippy 的 `let_underscore_untyped`或`let_underscore_must_use` lint,这个问题本可被标出,但遗憾的是这些 lint 并没有默认开启。

除此之外,还有声音质疑 Cloudflare 的监控能力:

Cloudflare 是在大规模发送错误响应并且直到客户投诉才察觉到这一点吗?这本应通过采样以及对若干回复的 lint 检查提前发现。

修复及其配套测试已经被合并进了hyper项目,将在未来的发布中提供,以防止该响应截断问题再次发生。

查看英文原文:Cloudflare Identifies Race Condition in hyper’s HTTP/1 Implementation