安全系统编程为何生锈

2020-10-24 08:11:23

在本系列中,我们探讨了采取主动措施消除一类漏洞的必要性,并介绍了我们在Microsoft代码中发现的一些使用其他语言本可以避免的内存安全问题的示例。现在,我们将了解为什么我们认为Rust代表了当前可用的C和C++的最佳替代方案。

首先,已经有大量出色的内存安全语言可用,并在Microsoft内外广泛使用,包括.NET语言(如C#或F#)以及其他语言(如SWIFT、GO和Python)。我们鼓励当前使用C或C++的任何人考虑是否适合使用这些语言中的一种。然而,我们谈论的是对安全系统编程语言的需求(即,一种可以构建其他软件运行在其上的系统的语言,如操作系统内核)。这样的工作负载需要C、C++和Rust提供的速度和可预测的性能。通过垃圾收集实现内存安全的语言不是系统编程的理想选择,因为它们的运行时可能导致不可预测的性能和不必要的开销。

当思考为什么Rust是一个很好的选择时,最好考虑一下从C或C++切换到我们不能放弃的东西--即性能和控制。就像C和C++一样,Ruust有一个最小且可选的“运行时”。Rust的标准库依赖于像C和C++一样支持它的平台的libc,但是标准库也是可选的,所以也可以在没有操作系统的平台上运行。

与C和C++一样,Rust也为程序员提供了对何时分配内存以及分配多少内存的细粒度控制,从而使程序员能够非常清楚地了解程序每次运行时将如何执行。就原始速度、控制和可预测性而言,这对性能意味着什么,那就是Rust、C和C++可以用类似的术语来考虑。

Rust语言与C和C++的不同之处在于其强大的安全性保证。除非明确选择不使用“不安全”关键字,否则Rust是完全内存安全的,这意味着我们在上一篇文章中说明的问题是无法表达的。在以后的帖子中,我们将重温这些示例,看看Rust通常是如何在不增加任何运行时开销的情况下预防这些问题的。正如我们所看到的,MSRC分配给CVE的大约70%的安全问题都是内存安全问题。这意味着如果该软件是用Rust编写的,那么这些安全问题中的70%很可能已经被消除了。我们并不是唯一一家报道过这样的发现的公司。

在系统编程中,有时程序员必须执行无法静态验证为安全的操作。Rust为程序员提供了将这些操作包装在安全抽象中的工具,这意味着曾经归入代码注释或约定的内容可以由Rust编译器静态强制执行。此外,必须明确标记内存不安全操作,从而大大减少安全专业人员必须仔细检查内存安全漏洞的外围应用。

由于上述原因,Rust最初引起了MSRC的兴趣,而微软的其他团队则出于其他原因开始采用Rust。

根据一项内部调查,采用该软件的首要原因是“正确性”--这是拉斯特安全保证的延伸,有助于实现“如果它编译了,那么它就能工作”这句谚语。

Rust在内存安全之外静态地强制执行程序的许多属性,包括空指针安全和数据竞争安全(即,不从两个或更多线程不同步地访问一块内存)。

微软的许多团队都发现,Rust的丰富类型系统使编写富有表现力的程序成为可能。带关联数据的枚举和强大的特征系统等概念进一步强化了Rust使程序尽可能无bug的目标。

Rust现有的社区对这种语言来说是一个巨大的好处。语言的大部分功能来自于其核心之外的库、工具和学习材料。虽然Rust还是一种年轻的语言,但它拥有一个健康的生态系统,拥有活跃和开放的编译器和语言开发过程,它显示了既能促进强大的开源社区,又能支持生产用户的能力。这给了我们更多的理由相信这门语言有一个光明的未来。

所有这些都解释了Rust在过去四年中荣登Stack Overflow最受欢迎语言排行榜榜首的记录。虽然现在就断言Rust在微软工程组织的规模上是什么样子还为时过早,但Rust的早期采用总体上是非常积极的。

我们相信,当涉及到编写安全系统软件时,Rust会改变游戏规则。RUST提供编写低级系统所需的性能和控制,同时使软件开发人员能够编写健壮、安全的程序。

在研究锈蚀的过程中,我们发现了一些让我们并将继续犹豫的问题。其中一些问题包括如何规模化地管理“不安全”的Rust超集的使用,缺乏与C++的一流互操作性,以及与现有Microsoft工具的互操作性。我们将在未来的博客中记录其中的许多内容,因为它们确实对微软规模的采用构成了挑战,我们希望让Rust和更广泛的软件社区参与帮助我们找到适用于所有人的解决方案。

但我们对这些可能性感到兴奋。虽然关于Rust如何适应整个微软工程故事还有很多问题要解决,我们鼓励其他人和我们一起认真研究一下适合他们系统编程需要的语言。