编写完10万行代码,我发了篇长文吐槽Rust

编写完10万行代码,我发了篇长文吐槽Rust
2022年06月25日 12:57 机器之心Pro

存在一种完美的编程语言吗?

Rust 语言因其并发安全性而深受众多开发者的喜爱,曾在多个榜单上获评最受欢迎编程语言。然而,现在有人花费大量时间编写 10 万行 Rust 代码之后,撰写博客阐明 Rust 语言的一系列缺点,以下是博客的主要内容。

我深入研究 Rust 是为了改进由 Xobs 编写的 Xous 操作系统。Xous 是一个用纯 Rust 编写的微内核消息传递操作系统,是为了轻量级 (IoT / 嵌入式规模) 的安全优先平台(例如 Precursor)而编写的,用于 MMU 的硬件强制型页面级内存保护。

一年来,我们为 Xous 操作系统添加了许多功能,包括网络 (TCP/UDP/DNS)、用于模态和多语言文本的中间件图形抽象、存储(以加密的形式)、PDDB、可信启动(trusted boot)以及密钥管理库等。

我们决定编写自己的操作系统而不是使用 SeL4、Tock、QNX 或 Linux 等现有实现,是因为我们想真正了设备中每一行代码都在做什么。特别是对于 Linux,它的源代码库非常庞大且动态,即使开源,也不可能搞清其内核中的每一行代码。因此,Xous 仅支持我们的平台,以尽可能避免内核不必要的复杂性。

这样减少应用范围还意味着我们还可以充分利用 CPU 在 FPGA 中运行的优势 。因此,Xous 以一种不寻常的 RV32-IMAC 配置为目标:具有 MMU + AES 扩展的配置。

FPGA 意味着我们有能力在硬件级别上修复 API 错误,从而使内核更加精简。这对于从 RAM 中处理诸如挂起和恢复之类的抽象破坏(abstraction-busting)进程尤其重要。

我们创建 Xous 时研究了大量的系统编程语言,最终 Rust 脱颖而出。当时它刚刚开始支持 `no-std`,它的特点是强类型、内存安全,具有良好的工具和新型生态系统。我个人是强类型语言的忠实拥护者,而内存安全性不仅有利于系统编程,还能使优化器更好地生成代码,并且 Rust 适用于并发。

实际上,我希望 Precursor 有一个支持标记指针和内存功能的 CPU,类似于 CHERI。于是我们和 CHERI 研发团队进行了一些讨论,但显然他们非常专注于 C 语言,也没有足够的带宽来支持 Rust。总体而言,C 比 Rust 需要 CHERI 多得多,他们的选择是符合资源优先原则的。我们不使用 C 语言,但出于安全性考虑,我希望有一天 Rust 中会存在硬件强制型胖指针(fat pointer)。

然而,Rust 语言绝不是完美的,甚至给我们的开发带来了很多问题。下面我列举一下 Rust 的缺点。

语法混乱复杂

我发现 Rust 语法密集、繁重且难以阅读,例如:

Trying::to_read::<&'a heavy>(syntax, |like| { this. can_be( maddening ) }).map(|_| ())?;

简单来说,上面的代码类似于在对象(实际上是 `struct`)上调用一个名为「to_read」的方法。

还有一种不遵循 Rust 语法规则的宏和指令也能运行:

#[cfg(all(not(baremetal), any(feature = “hazmat”, feature = “debug_print”)))]

上面的语句中最令我困惑的是使用‘=’来表示等价而不是赋值,因为配置指令中的内容不是 Rust 代码,它就像一个完全独立的元语言。

再比如,Rust 宏的可读性也存在问题——即使是我自己编写的一些 Rust 宏也「只是勉强工作」。

一种可靠的语言不应该存在这些语法问题。

Rust 的确很强大,它的标准库中包含 HashMaps、Vecs 和 Threads 等数据结构,丰富且可用性高。然而,Rust 的「std」库并没有为我们构建可审计的代码库带来任何好处。

Rust 不够完善

我们编写 Xous 的代码时,引入了一个叫作「const generic」的新类型。在此之前,Rust 没有原生能力来处理多于 32 个元素的数组,这个限制令人抓狂。

在编写 Xous 的过程中,Rust 的内联汇编、工作空间等功能逐渐成熟,这意味着我们需要重新审视已经写好的代码,以使关键的初始启动代码集成进我们构建的系统。

Xous 开发的第一年都是使用’no-std’完成的,代价是占用大量内存空间且复杂性高。尽管可以编写一个只有预先分配的、静态大小的数据结构的操作系统,但为了适应最坏情况下的元素数量,因此我们不得不推出一些自己的数据结构。

大约一年前,Xobs 将 Rust 的 `std` 库移植到 Xous,这意味着我们可以在稳定的 Rust 中访问堆,现在 Xous 与特定版本的 Rust 绑定。

`std` 库从根本上将内存分配、线程创建等「不安全」的硬件结构转变成了「安全」的 Rust 结构。

然而,我必须不断提醒自己,拥有 `std` 库并不能消除关键代码中的安全漏洞风险——它只是将许多关键代码移动到标准库中。

Rust 有固定的更新周期,这意味着我们也必须定期更新 Xous ,以保持与语言的兼容性。

但这可能是不可持续的。最终,我们需要锁定代码库,但我没有明确的退出策略。也许我们可以考虑仍然使用 `no-std` 以获得稳定的 `alloc` 功能来访问堆。但这样我们就还需要使用 Vec、HashMap、Thread 和 Arc/Mutex/Rc/RefCell/Box 构造等,以使 Xous 能够被有效编码。

Rust 在供应链安全方面堪忧

在 rustup.rs 安装文件中有如下代码:

`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`

用户可以下载脚本并在运行之前对其进行检查,这似乎比 vscode 的 Windows .MSI 安装程序好得多。但是,这种做法遍及整个构建生态系统,让我对通过 crates.io 生态系统发起的软件供应链攻击的可能性感到不安。

Crates.io 也存在一种拼写错误,很难确定哪些 crate 是好或坏;一些完全按照用户想要的名称命名的 crate 放弃提供所需功能,而积极维护的 crate 必须采用不太直观的名称。当然,这不是 Rust 独有的问题。

还有一个事实是,依赖项是链式的。也就是说当你从 crates.io 拉入一个东西时,你也会拉入该 crate 的所有从属依赖项,以及它们所有的 build.rs (http://build.rs/) 脚本,这些最终都将在你的机器上运行。因此,仅审核 Cargo.toml 文件中明确指定的 crate 是不够的——您还必须审核所有相关 crate 是否存在潜在的供应链攻击。

幸运的是,Rust 确实允许您使用 Cargo.lock 文件将 crate 固定在特定版本,并且可以完全指定依赖 crate 。我们试图在 Xous 中通过发布 Cargo.lock 文件并将我们所有的一阶相关 crate 指定为次要修订的策略来缓解这个问题。

然而,我们的大部分调试和测试框架都依赖于一些相当花哨和复杂的 crate,这些 crate 引入了大量的依赖项,即使我尝试为我们的目标硬件运行构建,在主机上运行的依赖 crate 和 build.rs 脚本还是被构建。

针对这个问题,我编写了一个名为「crate-scraper」的小工具,它为我们的 Cargo.toml 文件中指定的每个源下载源包,并且将它们存储在本地,这样我们就可以获得用于构建 Xous 版本的代码快照。

它还运行一个快速的「分析」程序——搜索名为 build.rs 的文件并将它们整理到一个文件中,这样我就可以更快地通过 grep 查找明显的问题。当然,手动审查并不是检测嵌入在 build.rs (http://build.rs/) 文件中巧妙伪装的恶意软件的实用方法,但它至少让我了解了我们正在处理的攻击面的规模。令人惊讶的是,我们审查出来自各种第三方的大约 5700 行代码,用于操作文件、目录和环境变量,并在我的计算机上运行其他程序。

我不确定这个问题是否有更好的解决方案,但是,如果你的目标是构建可信赖的固件,请警惕 Rust 广泛的软件供应链攻击面。

无法复现别人的 Rust 构建

我对 Rust 的最后一点看法是,一台计算机上的构建无法在另一台上复现。

我认为这主要是因为 Rust 将源代码的完整路径作为内置到二进制文件中调试字符串的一部分。这导致了一些糟糕的情况,例如我们在 Windows 上构建的工作成功了,但在 Linux 下却失败了,因为二者的路径名非常不同,这会导致一些内存对象在目标内存中被转移。

公平地讲,这些失败是由于 Xous 中存在错误,这些错误已经得到修复。但是,最终仍会有用户向我们报告我们无法复现,因为他们在构建系统上的路径与我们的不同。

最后,我想说尽管这里列出了所有的怨言,但如果能重来,Rust 仍然是我们用于构建 Xous 所用语言的有力竞争者。我用 C、Python 和 Java 完成了很多大型项目,所有这些项目最终都背负着「不断增加的技术债务」,而 Rust 可以规避这些问题。

操作系统内存
新浪科技公众号
新浪科技公众号

“掌”握科技鲜闻 (微信搜索techsina或扫描左侧二维码关注)

创事记

科学探索

科学大家

苹果汇

众测

专题

官方微博

新浪科技 新浪数码 新浪手机 科学探索 苹果汇 新浪众测

公众号

新浪科技

新浪科技为你带来最新鲜的科技资讯

苹果汇

苹果汇为你带来最新鲜的苹果产品新闻

新浪众测

新酷产品第一时间免费试玩

新浪探索

提供最新的科学家新闻,精彩的震撼图片