Canonical正在探索自动化工具能否将遗留C代码改写为安全、可维护的Rust代码,同时不改变软件的原有行为。为此,布里斯托大学的研究人员正在用AppArmor和snap-confine对该工具进行高难度测试。
AppArmor负责约束应用程序的权限,snap-confine则负责创建snap软件包运行所需的沙箱环境。两者都承担着安全关键任务。Canonical目前并不急于用Rust重写这两个组件,但希望弄清楚:在信任自动化翻译的生产代码之前,维护者究竟需要哪些证据。
Canonical提出的系统将使用大语言模型生成Rust代码,然后通过一套验证流程来发现并修复行为差异。这一方案背后有一个清醒的认识——大规模生成代码已经不再是难题,真正的难题在于证明代码的实际行为与原版一致。
AI生成的Rust代码可以顺利通过编译,却仍然与原始C代码的行为存在差异。研究人员计划将模糊测试与形式化程序分析结合起来,对两套实现进行比对,从而发现常规测试可能遗漏的差异。
一旦系统检测到不一致,就会采用符号化修复技术来精确定位故障原因并直接修复代码。这一反馈机制对于解决unsafe滥用问题至关重要。
Rust中的unsafe块允许执行安全Rust所不允许的操作,包括某些形式的原始指针操作。翻译工具可能依赖它来处理难以转换的C语言结构,但过度依赖unsafe会将原有的内存安全风险带入新代码中。
真正的目标是生成既足够安全、能够体现Rust语言优势,又在行为上与原始C代码高度一致、足以获得维护者信任的Rust代码。
AppArmor是检验这一目标是否可行的理想测试对象,因为翻译过程中的任何错误都可能带来安全后果。这个Linux安全模块根据预定义策略限制应用程序的访问权限,其周边的用户空间工具——由C、Python和C++混合编写——必须正确解析、编译并加载这些策略。如果Rust移植版本对某条策略的解读与现有实现不同,它可能编译完全正常,结果却是错的。正如AI辅助开发领域的从业者所知道的,通过所有测试的代码仍然可能以出人意料的方式引发问题。
snap-confine也面临类似挑战,因为它负责帮助建立snap软件包所使用的执行环境和隔离机制。将C代码重写为Rust可以消除整类漏洞,包括释放后使用和缓冲区溢出,但自动化翻译工具仍然可能引入逻辑错误。布里斯托团队必须证明翻译后的功能行为与原始C代码完全一致。
要充分发挥Rust的优势,往往不能仅仅逐行翻译C语言语法。编写地道的Rust代码可能需要对数据结构和多个函数乃至整个模块的生命周期管理进行调整。自动化翻译工具可以依靠unsafe来贴近原始C代码,但这样做存在将同类漏洞带入Rust代码的风险。
正因如此,Canonical资助布里斯托团队来寻找答案:这种方法能否扩展至包含数十万行C代码的完整代码库?
数十年来构建的操作系统、库和基础设施至今仍以C语言编写,其中大量软件仍处于积极维护和部署状态。手工重写这些代码需要耗费大量工程资源,且可能引入新的功能退化问题。但大规模生成代码本身已是可解决的问题,真正的瓶颈在于开发者的信任。Canonical与布里斯托大学的合作,正是在攻克这一核心难题——证明生成的Rust代码既具备内存安全性,又在功能上与沿用数十年的C代码完全等价。
Q&A
Q1:Canonical为什么要资助将C代码自动翻译成Rust的研究?
A:Canonical希望找到证据,证明自动化工具能够将遗留C代码安全地翻译为Rust,同时不改变原有行为。大规模代码生成本身已不是难题,关键在于让维护者相信翻译结果是可信的。Canonical资助布里斯托大学的研究,正是为了回答这个问题:验证流程能否证明生成的Rust代码在功能上与原始C代码完全一致。
Q2:AI生成的Rust代码编译通过了,为什么还不够安全?
A:编译通过只说明代码语法正确,并不保证行为与原始C代码一致。AI生成的Rust代码可能在逻辑上存在细微差异,导致在某些边界情况下产生不同结果。此外,翻译工具如果大量使用unsafe块来处理复杂的C语言结构,还会将原本的内存安全风险带入Rust代码,失去使用Rust的意义。
Q3:研究团队用什么方法来验证翻译后的Rust代码是否正确?
A:研究团队计划将模糊测试与形式化程序分析结合使用,对C和Rust两套实现进行系统性比对,捕捉常规测试可能遗漏的行为差异。一旦发现不一致,系统会采用符号化修复技术精确定位问题并自动修复,形成完整的检测与修复闭环。
