仅 5 天!Rust 刚入编 Linux 内核,首个 CVE 漏洞就来了

2025年12月11日,Rust语言在Linux内核的开发历程迎来关键转折——经过多年实践验证,Rust正式结束“实验”状态,成为Linux内核开发的稳定支持语言。这不仅是一次技术升级,更标志着安全、开源协作与系统编程未来的深度融合。

然而本周二(12月16日),CVE数据库正式披露了Linux 内核中首个涉及 Rust 代码的安全漏洞(漏洞编号:CVE-2025-68260)。

作为 Rust 进驻 Linux 内核后的 "首秀翻车" 事件,这个消息让不少人心里咯噔一下——当初引入Rust不就是为了提升安全性吗?怎么刚转正就出问题了?

这部分出问题的代码来自rust_binder模块,是 Google 专为 Android 系统开发的 Rust 版 Binder 驱动程序,于 Linux 内核 6.18 版本首次引入。以下是这个漏洞的详情:

Linux C/C++技术~更多 务实、能看懂、可复现 的技术文章和学习包尽在公众呺【Linux教程】

一、漏洞详情

1. 漏洞关键信息

2. 漏洞触发根源:unsafe 代码的同步缺失

问题出在rust_binder模块中处理 "死亡通知链表"(death_list)的一段 unsafe Rust 代码:

unsafe { node_inner.death_list.remove(self) };

这段代码的设计初衷是从链表中移除当前节点,但存在两个致命缺陷:

  1. 逻辑假设与实际不符:注释认为NodeDeath实例仅属于其所有者的death_list,但实际运行中可能存在多线程并发访问
  2. 缺乏同步保护:操作链表指针(prev/next)时未加锁,导致多线程同时修改链表结构

当多个线程并发执行链表移除操作时,会出现 "并发修改冲突":一个线程正在修改链表指针,另一个线程却试图访问已被篡改的指针,最终引发内存访问错误(如分页请求故障),直接导致内核崩溃(kernel panic/Oops)。

3. 影响范围与修复方案

受影响版本:Linux 内核 6.18 及以上(rust_binder从 6.18 版本开始引入)

修复思路:关闭竞态条件窗口,确保链表操作全程在锁保护下进行

修复代码对比

diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs
index 08d362deaf61e5..c26d113ede9668 100644
--- a/drivers/android/binder/node.rs
+++ b/drivers/android/binder/node.rs
@@ -541,10 +541,10 @@ impl Node {
             guard = self.owner.inner.lock();
         }
-        let death_list = core::mem::take(&mut self.inner.access_mut(&mut guard).death_list);
-        drop(guard);
-        for death in death_list {
+        while let Some(death) = self.inner.access_mut(&mut guard).death_list.pop_front() {
+            drop(guard);
             death.into_arc().set_dead();
+            guard = self.owner.inner.lock();
         }
     }

修复逻辑解析

原代码:一次性取出整个death_list并释放锁,在无锁窗口中迭代处理所有元素 —— 此时其他线程可能并发修改链表,导致指针失效

修复后:采用循环逐个弹出(pop_front)链表元素的方式,处理单个元素前释放锁,处理完成后重新加锁。这种设计彻底消除了长时间无锁窗口,确保每次链表操作都处于同步保护之下。


二、漏洞影响

1. 严重性评级

综合安全机构评级:中等偏高(部分机构标记为High)。

核心依据是:该漏洞仅影响系统稳定性,不涉及权限提升、远程代码执行等高危安全威胁,属于本地拒绝服务(DoS)类型漏洞,预计CVSS评分区间为5-7分。

2. 潜在后果与影响场景

3. 应急处置建议


三、Rust 还 "安全" 吗?

首个 Rust 内核 CVE 的出现,"Rust 的内存安全神话是不是破灭了?"

其实不然,因为Rust "安全" 的定义与边界 —— 它并非 "绝对无漏洞",而是 "在特定范围内提供可证明的安全保障"。

1. Rust 安全的核心承诺(仅限安全 Rust)

Rust 的安全保障是编译器强制执行的,无需垃圾回收,主要包括:

这些保障就像一面 "自动防护盾",只要不使用unsafe关键字,编译器会在编译期拦截所有潜在的安全风险 —— 这也是 Rust 相较于 C/C++ 的核心优势。

2. unsafe 代码:安全与灵活的妥协

Rust 设计unsafe关键字的初衷,是为了应对系统编程的特殊场景:

但unsafe会 "关闭编译器的安全检查",将安全责任完全交给开发者 —— 这意味着:

整体来讲Rust 的安全是 "缩小风险范围",而非 "消灭所有风险"

这个 CVE 漏洞并非 Rust 的失败,反而印证了其设计逻辑的合理性:

Rust 不能保证你写出的代码 "没有 bug",但能保证 "你的代码不会出现低级且致命的内存 / 线程安全 bug"—— 而这类 bug 正是 C/C++ 内核漏洞的重灾区(占比超 70%)。


四、系统编程中Rust的正确姿势

"如何在系统编程中正确使用 Rust":

  1. 谨慎使用 unsafe:仅在绝对必要时使用 unsafe,且尽量缩小代码块范围(如本次漏洞的 unsafe 代码可进一步优化同步逻辑)
  2. 并发场景必加锁:内核等多线程环境中,即使是 Rust 代码,对共享数据的操作也必须有明确的同步机制(锁、原子操作等)
  3. 不依赖 "安全语言" 的光环:Rust 降低了安全门槛,但不能替代开发者的安全意识 —— 系统编程的核心风险(如逻辑错误、配置不当)依然需要通过代码审查、测试来规避
  4. Rust 的优势依然存在:相较于 C/C++,Rust 已将大部分安全风险拦截在编译期,本次漏洞若用 C/C++ 实现,可能会引发更严重的内存破坏(如代码执行漏洞),而 Rust 仅导致内核崩溃


总结

Rust 的价值在于 "大幅降低安全风险的同时,不牺牲性能与灵活性"。

随着 Rust 在 Linux 内核中的应用逐渐深入,类似的 "初期磨合漏洞" 可能还会出现,但这正是技术演进的必经之路 —— 而 Rust 带来的安全红利,终将在长期实践中逐渐显现。

展开阅读全文

更新时间:2025-12-22

标签:科技   内核   漏洞   代码   系统   指针   线程   内存   风险   操作   逻辑

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020- All Rights Reserved. Powered By bs178.com 闽ICP备11008920号
闽公网安备35020302034844号

Top