Arm Community
Arm Community
  • Site
  • User
  • Site
  • Search
  • User
  • Groups
    • Arm Research
    • DesignStart
    • Education Hub
    • Graphics and Gaming
    • High Performance Computing
    • Innovation
    • Multimedia
    • Open Source Software and Platforms
    • Physical
    • Processors
    • Security
    • System
    • Software Tools
    • TrustZone for Armv8-M
    • 中文社区
  • Blog
    • Artificial Intelligence
    • Automotive
    • Healthcare
    • HPC
    • Infrastructure
    • Innovation
    • Internet of Things
    • Machine Learning
    • Mobile
    • Smart Homes
    • Wearables
  • Forums
    • All developer forums
    • IP Product forums
    • Tool & Software forums
  • Activity
  • Support
    • Open a support case
    • Documentation
    • Downloads
    • Training
    • Arm Approved program
    • Arm Design Reviews
  • More
  • Cancel
System
  • Developer Community
  • IP Products
  • System
  • Jump...
  • Cancel
System
Embedded blog How ARM Compiler detects stack overflows or malicious tampering
  • Blogs
  • Forums
  • Videos & Files
  • Mentions
  • Sub-Groups
  • Tags
  • Jump...
  • Cancel
  • New
More blogs in System
  • Embedded blog

  • SoC Design blog

Tags
Actions
  • RSS
  • More
  • Cancel
Related blog posts
Related forum threads

How ARM Compiler detects stack overflows or malicious tampering

Daniel Owens
Daniel Owens
September 11, 2013

Stack buffer overflows are an all too common failure mode in embedded systems where a program accidentally, or maliciously, overwrites fixed-length buffers on the call stack resulting in loss of system integrity. This blog describes how the ARM Compiler incorporates a stack protection security feature which can prevent stack buffer overflows, thus improving overall system integrity.

Call Stack Basics

A call stack, or simply ‘stack,’ is a data structure that stores information about software subroutines which are active during software execution. When a subroutine is called, a ‘stack frame’ is created where pertinent data is stored, such as the subroutine’s return address, values to be passed from caller to callee, values to be returned to the caller, and stored values of local variables of the subroutine. If a second (nested) subroutine is called, a new stack frame is created in adjoining memory. A register called the stack pointer (SP) points to the bottom of the stack while the top of the stack is located at a fixed address. Figure 1 below shows an example stack based on the ARM Procedure Call Standard (PCS):

Problems arise when a program attempts to use more memory than the stack has available. For example, if a subroutine uses an array as a local variable, an application could overwrite the array by writing more values than the array was allocated, thus overwriting adjacent memory. Writing past the end of an array will corrupt any stack data following the array, which could include the stack frame return address. Here is an example:

#include <string.h>

void string_copy(char *p)

{

char small_buf[64]; //small_buf not big enough to hold large_buf

strcpy(small_buf,p); //usage of strcpy doesn’t allow for bounds checking

}

int main()

{

char large_buf[128];

string_copy(large_buf);

return 0;

}

The function string_copy begins copying large_buf value by value into small_buf, but small_buf is much smaller than the string being copied. Because the strcpy function copies without bounds checking, the routine will carry on until all 128 characters are written to small_buf, causing the buffer to overflow and large_buf values to begin overwriting other values on the stack, including other local variables, and potentially the stack frame return address. Best case, your program will simply crash. Worst case, the buffer overwrite is malicious and forces the return address to a sequence of code which enables unwanted control of your device.

Stack Protection – How it Works

The Stack Protection feature provided by the ARM Compiler protects against damaging or malicious buffer overruns by adding a user-defined value, called a Stack Guard, between vulnerable local variables, e.g. arrays with type char or wchar_t, and the stack frame return address. Figure 2 below shows an example of a protected call stack.

The Stack Guard has a copy stored in a user-defined memory location. The ARM Compiler automatically generates code which compares the Stack Guard value to its copy prior to loading the value of the return address into the Program Counter (PC). If the Stack Guard and its copy do not match, an error handler is called.

To further limit the potential damage caused by a stack buffer overrun, the ARM Compiler moves vulnerable types to the top of the stack, immediately preceding the Stack Guard. A copy of the Stack Guard is stored at another location and is used to check that the guard value has not been overwritten, indicating a buffer overflow.

The ARM Compiler offers command line options and predefined functions to help setup and manage the Stack Guard. These options include:

  • protect_stack : inserts a guard variable onto the stack frame for each function containing a vulnerable variable. The guard variable is inserted between any buffers and the return address entry. The compiler uses heuristics to determine which functions will be protected.
  • protect_stack_all : option adds this protection to all functions regardless of their vulnerability. Use this option to bypass the compiler heuristics or to get a worst case estimate when measuring performance impact of the stack protection feature.

For security reasons, the value of the Stack Guard and the location of the Stack Guard copy are defined by the user. The value of the Stack Guard is taken from a global variable defined within:

void *__stack_chk_guard;

The user should provide this variable with a suitable value, such as a random value. The value can change during the life of the program. A desirable implementation might be to have the value constantly changed by another thread. If the Stack Guard fails to match its copy, the following function is called:

void __stack_chk_fail(void);

Within this function, the user needs to implement the stack-corruption handler.

Summary

Poor programming techniques or malicious behaviour have the ability to paralyze or even hijack your device. Particular sources of vulnerability are array buffers on the program call stack. The ARM Compiler Stack Protection feature mitigates this risk by adding an extra level of security to your system.

Related Blog:
CoreMark and Compiler Performance

Anonymous
Embedded blog
  • Embedded blog: Functional Safety on Arm – Beyond Automotive

    Antonio Priore
    Antonio Priore
    Arm has moved a long way from the days where our only ‘safety’ requirement was to provide ECC or parity protections on CPU RAMs and we are now able to offer a number of System IP, GPUs, ISPs and NPUs as…
    • December 13, 2019
  • Embedded blog: Leading the Digital Transformation of the Car at IAA Frankfurt

    Andy Moore
    Andy Moore
    This week at IAA New Mobility World, to demonstrate the future of in-car experiences, we are exhibiting a market-ready, scalable infotainment and cockpit control system from MediaTek and Mobica, featuring…
    • September 13, 2019
  • Embedded blog: Unlocking Cortex-A53's Safety Potential

    James Scobie
    James Scobie
    Arm will be introducing a Software Test Library (STL) on the Cortex-A53 processor. This is the first applications processor to have self-test Library software provided by Arm.
    • August 22, 2019