随着越来越多的嵌入式设备相互连接,安全性已经成为几乎每个设备的主要组成部分。在过去几年中,我们已经看到了支持安全性的硬件技术的改进,如Arm TrustZone和多核微控制器。但是,许多安全漏洞是由糟糕的编程实践造成的。在某种程度上,部分问题源于传统的嵌入式编程语言,如C和C++没有内置内存安全。因此,嵌入式开发人员必须管理内存安全;因此,不良实践会导致安全漏洞。
近年来,软件行业越来越倾向于使用内存安全的程序语言。从基于微控制器的系统角度来看,Rust是很适合的语言。然而,切换语言并非易事。在我们研究各种嵌入式编程语言中的内存安全细节之前,让我们来探讨一些导致嵌入式系统中漏洞的内存安全问题。
内存安全风险
最常见的漏洞之一是缓冲区溢出。当读取或(更常见的是)写入数组边界之外的数据时,会发生缓冲区溢出。缓冲区溢出会导致内存损坏,如果处理得当,还会让对手注入可执行代码。利用注入的代码,对手可以使程序崩溃,收集用户、网络数据,并使系统为所欲为。
另一个经常被利用的漏洞与内存的分配和释放方式有关。例如,某个应用程序可能分配了内存,但从未释放它,从而导致内存泄漏。此外,应用程序可能会尝试访问已经释放的内存,这可能会导致崩溃,并有机会利用系统。
竞争条件也可能是漏洞的来源。例如,在嵌入式开发中,如果有两个任务或一个中断,而主程序正在读写一个内存位置,就可能发生争用情况。当从存储器位置读取时,另一个可能试图写入它。如果写入程序可以中断读取,则有可能在竞争条件下破坏读取值,从而导致崩溃或意外的系统行为。
内存安全的语言与不安全的语言
使用内存安全编程语言并不是保证所有内存安全漏洞都会消失的灵丹妙药。然而,如果使用得当,内存安全语言可以极大地减少应用程序中出现内存漏洞的机会。内存安全语言背后的想法是,开发人员不必做任何特殊的事情来保护内存。例如,如果你在Rust中编写了一个覆盖了缓冲区边界的程序,你可能会看到如下运行时错误:
内存安全结论
如果你在连接的设备上工作,软件中的内存安全是必要的。内存安全语言可以帮助开发人员更好更快地发现潜在的内存漏洞。真正的问题是将平台或产品线从现有语言转换到新语言。转换语言对你来说可能有意义,也可能没有意义。
虽然我们已经探讨了一些内存安全问题,但使用内存安全语言并不是必需的。嵌入式开发人员可以通过遵循语言最佳实践来提高应用程序的内存安全性。例如,有一些使用C和C++维护内存安全的最佳实践。然而,C、C++和Rust中的内存安全技术是不同的。