mirror of
https://github.com/ferrous-systems/embedded-trainings-2020.git
synced 2025-06-06 01:48:47 +00:00
Merge pull request #125 from ferrous-systems/stack_overflow
add Stack overflow extra exercise
This commit is contained in:
commit
68b40ca9d5
8 changed files with 139 additions and 0 deletions
2
.github/workflows/rust.yml
vendored
2
.github/workflows/rust.yml
vendored
|
@ -59,11 +59,13 @@ jobs:
|
||||||
- name: build and fmt beginner/apps
|
- name: build and fmt beginner/apps
|
||||||
working-directory: ./beginner/apps
|
working-directory: ./beginner/apps
|
||||||
run: |
|
run: |
|
||||||
|
cargo install flip-link
|
||||||
cargo build --verbose
|
cargo build --verbose
|
||||||
cargo fmt --all -- --check
|
cargo fmt --all -- --check
|
||||||
|
|
||||||
- name: build and fmt advanced/firmware
|
- name: build and fmt advanced/firmware
|
||||||
working-directory: ./advanced/firmware
|
working-directory: ./advanced/firmware
|
||||||
run: |
|
run: |
|
||||||
|
cargo install flip-link
|
||||||
cargo build --verbose
|
cargo build --verbose
|
||||||
cargo fmt --all -- --check
|
cargo fmt --all -- --check
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||||
|
# (..)
|
||||||
|
rustflags = [
|
||||||
|
"-C", "linker=flip-link", # adds stack overflow protection
|
||||||
|
# (..)
|
||||||
|
]
|
||||||
|
|
||||||
[target.thumbv7em-none-eabihf]
|
[target.thumbv7em-none-eabihf]
|
||||||
runner = "probe-run --chip nRF52840_xxAA"
|
runner = "probe-run --chip nRF52840_xxAA"
|
||||||
rustflags = [
|
rustflags = [
|
||||||
|
|
34
advanced/firmware/src/bin/stack_overflow.rs
Normal file
34
advanced/firmware/src/bin/stack_overflow.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use cortex_m::asm;
|
||||||
|
use cortex_m_rt::entry;
|
||||||
|
use panic_log as _; // panic handler
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
// board initialization
|
||||||
|
dk::init().unwrap();
|
||||||
|
|
||||||
|
log::info!("provoking stack overflow...");
|
||||||
|
spam(0);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
asm::bkpt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn spam(n: u32) {
|
||||||
|
// allocate and initialize 4 kilobytes of stack memory to provoke stack overflow
|
||||||
|
let use_stack = [n; 1024];
|
||||||
|
|
||||||
|
log::info!(
|
||||||
|
"address of current `use_stack` at recursion depth {:?}: {:?}",
|
||||||
|
use_stack[1023], // "use" use_stack to prevent it from being optimized out
|
||||||
|
&use_stack as *const u32
|
||||||
|
);
|
||||||
|
|
||||||
|
let next = n + 1;
|
||||||
|
spam(next); // infinite recursion
|
||||||
|
}
|
|
@ -1,3 +1,10 @@
|
||||||
|
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||||
|
# (..)
|
||||||
|
rustflags = [
|
||||||
|
"-C", "linker=flip-link", # adds stack overflow protection
|
||||||
|
# (..)
|
||||||
|
]
|
||||||
|
|
||||||
[target.thumbv7em-none-eabihf]
|
[target.thumbv7em-none-eabihf]
|
||||||
runner = "probe-run --chip nRF52840_xxAA"
|
runner = "probe-run --chip nRF52840_xxAA"
|
||||||
rustflags = [
|
rustflags = [
|
||||||
|
|
30
beginner/apps/src/bin/stack_overflow.rs
Normal file
30
beginner/apps/src/bin/stack_overflow.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use cortex_m::asm;
|
||||||
|
use cortex_m_rt::entry;
|
||||||
|
use panic_log as _; // panic handler
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
// board initialization
|
||||||
|
dk::init().unwrap();
|
||||||
|
|
||||||
|
log::info!("fib(100) = {:?}", fib(100));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
asm::bkpt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn fib(n: u32) -> u32 {
|
||||||
|
// allocate and initialize one kilobyte of stack memory to provoke stack overflow
|
||||||
|
let _use_stack = [0xAA; 1024];
|
||||||
|
|
||||||
|
if n < 2 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
fib(n - 1) + fib(n - 2) // recursion
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,6 +57,7 @@
|
||||||
- [Inspecting the Descriptors](./inspecting-descriptors.md)
|
- [Inspecting the Descriptors](./inspecting-descriptors.md)
|
||||||
- [Getting it Configured](./getting-device-configured.md)
|
- [Getting it Configured](./getting-device-configured.md)
|
||||||
- [Next Steps](./advanced-next-steps.md)
|
- [Next Steps](./advanced-next-steps.md)
|
||||||
|
- [Stack Overflow Protection](./stack-overflow-protection.md)
|
||||||
- [References and Resources](./references-resources.md)
|
- [References and Resources](./references-resources.md)
|
||||||
- [Tooltips](./tooltips.md)
|
- [Tooltips](./tooltips.md)
|
||||||
- [Troubleshooting](./troubleshooting.md)
|
- [Troubleshooting](./troubleshooting.md)
|
||||||
|
|
|
@ -143,6 +143,10 @@ Installed package `cargo-binutils v0.3.3` (..)
|
||||||
$ cargo install probe-run
|
$ cargo install probe-run
|
||||||
(..)
|
(..)
|
||||||
Installed package `probe-run v0.1.8` (..)
|
Installed package `probe-run v0.1.8` (..)
|
||||||
|
|
||||||
|
$ cargo install flip-link
|
||||||
|
(..)
|
||||||
|
Installed package `flip-link v0.1.2` (..)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Workshop specific tools
|
### Workshop specific tools
|
||||||
|
|
54
embedded-workshop-book/src/stack-overflow-protection.md
Normal file
54
embedded-workshop-book/src/stack-overflow-protection.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
# Stack Overflow Protection
|
||||||
|
|
||||||
|
The `firmware` crate in which we developed our advanced workshop solutions (i.e. `advanced/firmware`) uses our open-source [`flip-link`] tool for zero-cost stack overflow protection.
|
||||||
|
|
||||||
|
This means that your application will warn you by crashing if you accidentally overreach the boundaries of your application's stack instead of running into *undefined behavior* and behaving erratically in irreproducible ways. This memory protection mechanism comes at no additional computational or memory-usage cost.
|
||||||
|
|
||||||
|
🔎 For a detailed description of how `flip-link` and Stack Overflows in bare metal Rust in general work, please refer to the [`flip-link` README].
|
||||||
|
|
||||||
|
You can see this in action in the `stack_overflow.rs` file that can be found in `advanced/firmware/src/bin/`:
|
||||||
|
|
||||||
|
``` rust
|
||||||
|
{{#include ../../advanced/firmware/src/bin/stack_overflow.rs}}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `spam()` function allocates data on the stack until the stack boundaries are reached.
|
||||||
|
|
||||||
|
✅ Run `stack_overflow.rs`
|
||||||
|
|
||||||
|
You should see output similar to this:
|
||||||
|
|
||||||
|
``` console
|
||||||
|
(...)
|
||||||
|
(HOST) INFO flashing program (32.68 KiB)
|
||||||
|
(HOST) INFO success!
|
||||||
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
INFO:stack_overflow -- provoking stack overflow...
|
||||||
|
INFO:stack_overflow -- address of current `use_stack` at recursion depth 0: 0x2003aec0
|
||||||
|
INFO:stack_overflow -- address of current `use_stack` at recursion depth 1: 0x20039e50
|
||||||
|
(...)
|
||||||
|
INFO:stack_overflow -- address of current `use_stack` at recursion depth 10: 0x20030a60
|
||||||
|
INFO:stack_overflow -- address of current `use_stack` at recursionstack backtrace:
|
||||||
|
0: HardFaultTrampoline
|
||||||
|
<exception entry>
|
||||||
|
1: ???
|
||||||
|
error: the stack appears to be corrupted beyond this point
|
||||||
|
(HOST) ERROR the program has overflowed its stack
|
||||||
|
```
|
||||||
|
|
||||||
|
❗️ `flip-link` is a third-party tool, so make sure you've installed it through `cargo install flip-link`
|
||||||
|
|
||||||
|
To see how we've activated `flip-link`, take a look at `advanced/firmware/.cargo/config.toml`:
|
||||||
|
|
||||||
|
``` toml
|
||||||
|
{{#include ../../advanced/firmware/.cargo/config.toml::7}}
|
||||||
|
```
|
||||||
|
|
||||||
|
There, we've configured `flip-link` as the linker to be used for all ARM targets.
|
||||||
|
If you'd like to use `flip-link` in your own projects, this is all you need to add!
|
||||||
|
|
||||||
|
🔎 Note: if you try to run `stack_overflow.rs` *without* `flip-link` enabled, you might see varying behavior depending on the `rustc` version you're using, timing and pure chance. This is because undefined behavior triggered by the program may change between `rustc` releases.
|
||||||
|
|
||||||
|
|
||||||
|
[`flip-link`]: https://github.com/knurling-rs/flip-link
|
||||||
|
[`flip-link` README]: https://github.com/knurling-rs/flip-link/blob/main/README.md
|
Loading…
Reference in a new issue