10个版本
0.1.9 | 2024年8月14日 |
---|---|
0.1.8 | 2024年3月6日 |
0.1.7 | 2023年7月20日 |
0.1.6 | 2022年3月24日 |
0.1.2 | 2020年11月26日 |
#24 in 嵌入式开发
每月下载量 6,589次
58KB
516 代码行
flip-link
为您的嵌入式程序添加零成本的栈溢出保护
问题
裸金属Rust程序在存在栈溢出的情况下可能 不 是内存安全的。例如,基于v0.6.x版本的 cortex-m-rt
包的Rust程序就是这样。
以下程序,其中不包含 unsafe
代码块,如果达到栈溢出条件,可能会遇到 未定义的行为。
// static variables placed in the .bss / .data sections
static FLAG1: AtomicBool = AtomicU32::new(false); // .bss
static FLAG2: AtomicBool = AtomicU32::new(true); // .data
fn main() {
let _x = fib(100);
}
#[inline(never)]
fn fib(n: u32) -> u32 {
// allocate and initialize 4 kilobytes of stack memory
let _use_stack = [0xAA; 1024];
if n < 2 {
1
} else {
fib(n - 1) + fib(n - 2) // recursion
}
}
#[interrupt]
fn interrupt_handler() {
// does some operation with `FLAG1` and `FLAG2`
}
以下是在RAM中ARM Cortex-M程序默认内存布局的示例。
函数调用栈,也称为“栈”,在函数调用和创建局部变量(例如 let x
)时向下增长(这些变量也放在栈上)。
如果栈增长过大,则会与包含所有程序静态变量的 .bss + .data
区域冲突。这种冲突会导致静态变量被无关数据覆盖。这可能导致程序观察到静态变量处于无效状态:例如一个 AtomicBool
可能保持 3
的值 -- 这是因为Rust ABI期望这个单字节变量为 0
或 1
,这是未定义的行为。
解决方案
一个可能的解决方案是更改程序的内存布局,并将栈放置在 .bss+.data
区域 下方。
使用这种反转的内存布局(如图所示),堆栈不能与静态变量冲突。相反,它将与物理RAM内存区域的边界冲突。在ARM Cortex-M架构中,尝试读取或写入RAM区域的边界将产生“硬件异常”。cortex-m-rt
crate提供了一个API来处理这种条件:可以定义一个HardFault
异常处理程序;当尝试执行无效的内存操作时,将执行此“处理程序”(函数)。
flip-link
实现了这种堆栈溢出解决方案。将您的程序与flip-link
链接会产生反转的内存布局,在堆栈溢出情况下内存安全。
架构支持
flip-link
已知可以与链接到0.6.x
版本的cortex-m-rt
crate的ARM Cortex-M程序一起使用,并使用Rust工具链(LLD)提供的链接器进行链接。目前,它尚未与其他架构或运行时crate进行测试。
安装
flip-link
可在crates.io
获取。要安装它,运行
$ cargo install flip-link
使用
在.cargo/config.toml
中将链接器从rust-lld
(默认)更改为flip-link
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# (..)
linker = "flip-link"
在Cargo < 1.74版本中,使用rustflags
更改链接器
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# (..)
rustflags = [
"-C", "linker=flip-link", # <- add this
# (..)
]
请注意,如果您使用GNU ld
或GNU gcc
链接程序,则此方法不会起作用。其他链接器的支持正在问题#1中跟踪。
测试
我们的CI执行各种检查。您可以在本地运行它们以确保您的PR将通过CI
cargofmt --all ----check
cargoclippy ----deny warnings
cargoxtest
- 这将安装当前版本的
flip-link
并运行cargo test
。
- 这将安装当前版本的
支持
flip-link
是Knurling项目的一部分,是Ferrous Systems改进用于开发嵌入式系统工具的努力。
如果您认为我们的工作很有用,请考虑通过GitHub Sponsors进行赞助。
许可证
根据您的选择,许可为以下之一
-
Apache License,版本2.0(LICENSE-APACHE或http://apache.ac.cn/licenses/LICENSE-2.0)
。
贡献
除非您明确说明,否则根据Apache-2.0许可证定义的任何旨在包含在您的工作中的故意提交的贡献,均应按上述方式许可,而不附加任何其他条款或条件。
依赖项
~2.5MB
~45K SLoC