导读:法国国家信息和自动化研究院 (Inria) 和微软的计算机科学家们设计出一种方法,可以自动将 C 代码子集转换为安全的 Rust 代码,以满足日益增长的内存安全需求。
C 编程语言诞生于 20 世纪 70 年代初,用于构建许多关键型系统、应用程序和库。例如,Linux 内核主要是用 C 语言编写的。
但 C 语言和它的扩展 C++ 一样,并不是为内存安全而设计的,它采用手动内存管理,比自动内存管理(例如垃圾回收)更高效、更灵活,但也更容易出现内存错误。
近期的多项研究表明,内存安全错误(如越界读写和释放后使用)占软件漏洞的大多数。在谷歌的 Android 操作系统中,它们在 2019 年占漏洞总数的 76% ,而 Chocolate Factory 预测,通过使用 Rust 和安全编码实践,到 2024 年底,这一数字将降至 24% 。
Rust 代码可以编写为内存安全的或不安全的应用,这由开发人员自行决定。虽然 C 和 C++ 代码可以通过勤奋、静态分析和测试变得更加内存安全,但这两种编程语言都没有提供开箱即用的内存安全保证。
过去几年,业界与政府一直在努力减少 C 和 C++ 代码的使用,增加使用内存安全的编程语言,如 Rust、Go、Python 和 Java(尽管这些语言可能链接到不安全的库)。正如互联网安全研究小组 (ISRG) 的 Prossimo 项目所说:“使用 C 和 C++ 对社会有害,对你的声誉有害,对你的客户也有害。”
并不是每个人都会走得这么远。许多 C 和 C++ 程序员宁愿找到继续使用他们喜欢的工具的方法,而不是加入 Rust 大潮,甚至谷歌这样的大厂,作为 Rust 最直言不讳的布道者之一,也承认 C 和 C++ 代码将长期存在。
因此,我们付出了相当大的努力来开发使 C 和 C++ 更加内存安全的方法,并开发像DARPA 的 TRACTOR程序这样的自动代码转换机制。
像TrapC和Fil-C这样的努力使 C 内存安全,但也有其弊端。TrapC 仍在开发中,专注于语言的一个子集。Fil-C 目前会对性能造成影响,并且缺乏完整的应用程序二进制接口 (ABI) 兼容性。
在一篇题为《将 C 编译为安全的 Rust,形式化》的论文中,作者 Aymeric Fromherz(Inria)和 Jonathan Protzenko(Microsoft)提供了一种替代自动将 C 转换为 Rust 的方案 ,该方案会产生不安全的Rust。他们的重点是为经过形式化验证的工业级代码提供转换路径。
“C 允许程序员在别名、低级强制类型转换、内存管理和数据表示方面发挥创造力,”作者解释道。“在 Rust 中表达这些模式需要放弃许多静态保证,以便允许未经检查的别名、表示之间的强制类型转换(在 Rust 术语中也称为‘变形’)等,这是通过 Rust 的不安全特性实现的。但这样做会抹杀 Rust 的优势!”
因此,Fromherz 和 Protzenko 开发了 C 的一个子集,称为“Mini-C”,它避免了常见的 C 模式和特性,例如指针算法和隐式可变性,这些特性无法直接转换为安全的 Rust。
通过使用KaRaMeL编译器框架实现 Mini-C ,科学家们表示他们的方法可以生成安全的 Rust 代码,但需要注意的是可能需要进行一些重构。
他们解释说:“我们不会将 C 语言的全部通用性自动转换为不安全的 Rust 语言,并试图使生成的代码更安全,而是以面向数据的 C 语言应用子集为目标。因此,我们的翻译过程是半主动的:用户可能必须对源 C 程序进行最小的调整,以适应支持的语言子集;一旦进入这个子集,我们的方法就会自动生成有效、安全的 Rust 代码。”
他们在 HACL*(高保证加密库)上测试了转换过程,HACL* 是一个由 80,000 行 C 代码组成的经过验证的加密库,而在 EverParse 上,EverParse 是一个由 1,400 行 C 代码组成的经过验证的格式化程序和序列化程序库。
HACL* 转换只需要最少的代码更改,而 EverParse 转换无需更改源代码即可完成。他们声称,结果效果很好 - 尽管添加了胖指针和运行时边界检查,Rust 代码仍表现出与原始 C 代码相同的性能特征。
这项工作现在有助于使各种依赖应用程序更加安全。作者表示,他们用 Rust 编译的 HACL* 已打包在 libcrux 加密库中,其中部分内容已添加到 Mozilla 的NSS和 OpenSSH 中。
作者:聆听音乐的鱼
本文为 @ 场长 创作并授权 21CTO 发布,未经许可,请勿转载。
内容授权事宜请您联系 webmaster@21cto.com或关注 21CTO 公众号。
该文观点仅代表作者本人,21CTO 平台仅提供信息存储空间服务。