Tuesday, March 26, 2019

Prevent and Mitigate Stack Overflow

When programming micro-controllers you usually have to be more careful with your memory usage and also for smaller devices you often don't get any help from the hardware.

On ARM micro-controllers the memory layout is such that the stack is placed at the higher address range of the memory and writes 'downwards' towards the lower memory addresses. While the heap fills up memory from the lower to the higher addresses. In cases of high use of static/program memory use, heap use and stack use, the stack can overflow and overwrite heap memory. This may result in weird and undefined behavior. This is bad.

Some methods that can be used to prevent this:
  • Use the HW memory protection unit: HW unit that causes an interrupt or fault if stack is written passed a defined address.
  • Canary: Write a unique value to address designated as top of stack and check that this value is still written to top of stack address in main loop.
  • Add stack protection code: GCC can add functionality to check wether writes to stack would overflow. Results in larger program binary and higher overall stack usage.
  • Stack depth analysis: Compile time or static analysis of code to determine how much stack each function will use and combinations that would result in stack overflow. Some tools:
    • GCC -fstack-usage, doesn't work in combination with -lto (link time optimization).
    • ARM compiler, with Keil microvision (uvision), but gives only one number for each interrupt level.
  • Water mark: Fill stack with pattern for each main loop to, check stack usage after each automatic test. Create tests that you think will cause the most high stack usage functions to execute (preferably simultaneously/interrupted).

Well known case of this: https://developers.slashdot.org/story/14/02/21/2349204/stack-overflow-could-explain-toyota-vehicles-unintended-acceleration