Canonical 4 月披露了 uutils/coreutils 中的 44 个 CVE。uutils 是 GNU coreutils 的 Rust 重写版本,Ubuntu 自 25.10 起默认使用它,并在 26.04 LTS 发布前委托外部审计。审计结果解释了一个现实决定:在 26.04 LTS 中,cpmvrm 等部分关键工具仍保留 GNU 版本。

这不是一场“Rust 安不安全”的公投。更准确的判断是:Rust 能大幅减少悬垂指针、越界写、use-after-free 这类内存安全问题,但它不会自动理解 Unix 文件系统语义、权限窗口、非 UTF-8 字节和 CLI 退出码。对发行版和系统工具开发者来说,这批 CVE 更像一份生产级 Rust 系统代码的边界样本。

Canonical 的审计把 Rust 安全边界摊到台面上

uutils 的价值没有因为这次披露被否定。相反,团队公开审计细节,让外部开发者能看到真实系统工具迁移 Rust 时会踩在哪里。借用检查器、Clippy、cargo audit 各有覆盖范围:它们能约束所有权、发现部分代码坏味道、检查已知依赖漏洞,却不会替开发者判断两次 syscall 之间路径有没有被替换。

漏洞模式Rust 能帮什么Rust 不会自动保证什么系统工具里的后果
路径 TOCTOU避免内存悬垂两次按路径解析是否指向同一对象特权进程可能跟随符号链接改错文件
创建后再改权限提供安全 API 选择文件出生瞬间的权限窗口其他用户可能抢先打开句柄
UTF-8 转换保证 String 合法 UTF-8Unix 路径和流本来是原始字节输出被静默改写或工具拒绝处理
panic 与吞错Result 表达失败开发者是否传播错误cron、CI、脚本可能中断或误判成功

TOCTOU 是这次最典型的一类问题。程序先对某个路径做检查,再对同一路径执行写入、删除或改权限;在两次基于路径的 syscall 之间,有权限写父目录的攻击者可以把路径换成符号链接。内核第二次会重新解析路径,操作就可能落到攻击者选中的目标上。Rust 标准库中 fs::metadataFile::createfs::set_permissions 这类易用 API 都按路径工作,用在普通程序里方便,用在特权工具里就要格外小心。

更稳妥的做法是用文件描述符锚定对象。创建新文件时使用类似 create_new(true) 的原子语义;处理既有对象时,尽量打开父目录并相对该句柄操作。权限也应在创建时设定,而不是先 create_dirchmod,因为那个短暂窗口足够让别人拿到文件描述符。

Unix 工具处理的是字节,不是“看起来正常的字符串”

很多应用开发者默认把文本当 UTF-8,这在 Web 服务和桌面应用里通常合理。但 Unix 的路径、环境变量、命令参数和 cutcommtr 这类工具的输入流,本质上是字节序列。把它们随手转成 Rust 的 String,就已经改变了问题。

审计中有一类漏洞来自 lossy 转换或严格转换。前者会把非法字节替换成 U+FFFD,造成输出被改写;后者遇到非 UTF-8 就 unwrapexpect 或直接返回失败。GNU coreutils 的历史包袱在这里反而是一种规范:它长期按 Unix 规则处理字节,而不是替用户“纠正”编码。

这对 Rust 系统编程团队有直接影响。写 CLI 工具、备份脚本组件、发行版基础命令时,路径用 Path/PathBuf,环境变量用 OsString,输入输出流保留 &[u8]Vec<u8>。为了打印方便走一圈 String,省下的是几行代码,付出的可能是数据损坏或兼容性回退。

真正受影响的是发行版维护者和系统工具开发者

普通 Ubuntu 用户短期内未必感知这些 CVE。Canonical 在 LTS 前做审计,本来就是为了降低长期支持版本把问题固化五年的风险。更受影响的是两类人:维护基础命令的发行版团队,以及准备用 Rust 重写 C/C++ 系统组件的工程团队。

他们接下来要盯的不是“Rust 要不要用”,而是迁移后的验收标准是否足够接近原工具。GNU coreutils 不是只有功能列表,还有几十年积累出的边界行为:退出码怎么合并、错误能不能忽略、路径身份是比字符串还是比 dev/inode、非 UTF-8 文件名是否原样通过。

尤其要警惕 panic 和吞错。unwrapexpect、数组下标、未检查算术在处理不可信输入时可能变成拒绝服务;.ok()let _ =、只返回最后一个文件的错误码,则可能让脚本以为任务成功。对于跑在 cron、CI、安装器或恢复环境里的工具,一次静默失败比一次响亮报错更危险。

接下来最该观察 Ubuntu 26.04 LTS 对 uutils 的替换范围、回退工具清单和后续修复节奏。若 Canonical 能把这次审计沉淀成发行版级 Rust 系统工具规范,它的意义会超过 44 个 CVE 本身;若只把问题当成单个项目的 bug 清单,下一批重写工具仍会在同一类 Unix 语义里摔跤。