diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b43ae1e..e240dc899 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ESP32-S3: Added LCD_CAM I8080 driver (#1086) - Allow for splitting of the USB Serial JTAG peripheral into tx/rx components (#1024) - `RngCore` trait is implemented (#1122) +- Support Rust's `stack-protector` feature (#1135) ### Fixed diff --git a/esp-hal/ld/sections/stack.x b/esp-hal/ld/sections/stack.x index ea28a6fc1..e7e306934 100644 --- a/esp-hal/ld/sections/stack.x +++ b/esp-hal/ld/sections/stack.x @@ -34,3 +34,10 @@ PROVIDE(_stack_start = ORIGIN(RWDATA) + LENGTH(RWDATA)); PROVIDE(_stack_start_cpu0 = ORIGIN(RWDATA) + LENGTH(RWDATA)); #ENDIF + +/* +Provide the stack_guard for `stack-protector` + +Ideally the offset should be configurable - should be done once we have https://github.com/esp-rs/esp-hal/issues/1111 +*/ +PROVIDE(__stack_chk_guard = _stack_end + 4096); diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 2cfb005eb..be424eff2 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -448,3 +448,30 @@ impl FlashSafeDma { self.inner } } + +#[cfg(riscv)] +#[export_name = "hal_main"] +fn hal_main(a0: usize, a1: usize, a2: usize) -> ! { + extern "Rust" { + // This symbol will be provided by the user via `#[entry]` + fn main(a0: usize, a1: usize, a2: usize) -> !; + } + + extern "C" { + static mut __stack_chk_guard: u32; + } + + unsafe { + let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard); + // we _should_ use a random value but we don't have a good source for random + // numbers here + stack_chk_guard.write_volatile(0xdeadbabe); + + main(a0, a1, a2); + } +} + +#[export_name = "__stack_chk_fail"] +unsafe extern "C" fn stack_chk_fail() { + panic!("Stack corruption detected"); +} diff --git a/esp-hal/src/soc/esp32/mod.rs b/esp-hal/src/soc/esp32/mod.rs index 697a4bc5d..8bfef537e 100644 --- a/esp-hal/src/soc/esp32/mod.rs +++ b/esp-hal/src/soc/esp32/mod.rs @@ -46,6 +46,8 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { static mut _rtc_slow_bss_end: u32; static mut _stack_start_cpu0: u32; + + static mut __stack_chk_guard: u32; } // set stack pointer to end of memory: no need to retain stack up to this point @@ -58,6 +60,13 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { xtensa_lx_rt::zero_bss(&mut _rtc_fast_bss_start, &mut _rtc_fast_bss_end); xtensa_lx_rt::zero_bss(&mut _rtc_slow_bss_start, &mut _rtc_slow_bss_end); + unsafe { + let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard); + // we _should_ use a random value but we don't have a good source for random + // numbers here + stack_chk_guard.write_volatile(0xdeadbabe); + } + // continue with default reset handler xtensa_lx_rt::Reset(); } diff --git a/esp-hal/src/soc/esp32s2/mod.rs b/esp-hal/src/soc/esp32s2/mod.rs index 656ef673a..1ac3b106d 100644 --- a/esp-hal/src/soc/esp32s2/mod.rs +++ b/esp-hal/src/soc/esp32s2/mod.rs @@ -50,6 +50,8 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { static mut _rtc_slow_bss_end: u32; static mut _stack_start_cpu0: u32; + + static mut __stack_chk_guard: u32; } // set stack pointer to end of memory: no need to retain stack up to this point @@ -62,6 +64,13 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { xtensa_lx_rt::zero_bss(&mut _rtc_fast_bss_start, &mut _rtc_fast_bss_end); xtensa_lx_rt::zero_bss(&mut _rtc_slow_bss_start, &mut _rtc_slow_bss_end); + unsafe { + let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard); + // we _should_ use a random value but we don't have a good source for random + // numbers here + stack_chk_guard.write_volatile(0xdeadbabe); + } + // continue with default reset handler xtensa_lx_rt::Reset(); } diff --git a/esp-hal/src/soc/esp32s3/mod.rs b/esp-hal/src/soc/esp32s3/mod.rs index 9c3c52fe7..a75a839e4 100644 --- a/esp-hal/src/soc/esp32s3/mod.rs +++ b/esp-hal/src/soc/esp32s3/mod.rs @@ -85,6 +85,8 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { static mut _rtc_slow_bss_end: u32; static mut _stack_start_cpu0: u32; + + static mut __stack_chk_guard: u32; } // set stack pointer to end of memory: no need to retain stack up to this point @@ -97,6 +99,13 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { xtensa_lx_rt::zero_bss(&mut _rtc_fast_bss_start, &mut _rtc_fast_bss_end); xtensa_lx_rt::zero_bss(&mut _rtc_slow_bss_start, &mut _rtc_slow_bss_end); + unsafe { + let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard); + // we _should_ use a random value but we don't have a good source for random + // numbers here + stack_chk_guard.write_volatile(0xdeadbabe); + } + // continue with default reset handler xtensa_lx_rt::Reset(); } diff --git a/esp-riscv-rt/CHANGELOG.md b/esp-riscv-rt/CHANGELOG.md index 7c4227ae3..ea09d0c09 100644 --- a/esp-riscv-rt/CHANGELOG.md +++ b/esp-riscv-rt/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- `start_rust` calls `hal_main` instead of calling user's `main` directly (#1135) + ### Removed ## 0.6.1 - 2024-01-19 diff --git a/esp-riscv-rt/src/lib.rs b/esp-riscv-rt/src/lib.rs index e80a72bda..1bf559f1a 100644 --- a/esp-riscv-rt/src/lib.rs +++ b/esp-riscv-rt/src/lib.rs @@ -52,8 +52,7 @@ extern "C" { #[export_name = "_start_rust"] pub unsafe extern "C" fn start_rust(a0: usize, a1: usize, a2: usize) -> ! { extern "Rust" { - // This symbol will be provided by the user via `#[entry]` - fn main(a0: usize, a1: usize, a2: usize) -> !; + fn hal_main(a0: usize, a1: usize, a2: usize) -> !; fn __post_init(); @@ -65,7 +64,7 @@ pub unsafe extern "C" fn start_rust(a0: usize, a1: usize, a2: usize) -> ! { _setup_interrupts(); - main(a0, a1, a2); + hal_main(a0, a1, a2); } /// Registers saved in trap handler