You copied the Doc URL to your clipboard.

-fstack-protector, -fstack-protector-all, -fstack-protector-strong, -fno-stack-protector

Inserts a guard variable onto the stack frame for each vulnerable function or for all functions.

The prologue of a function stores a guard variable onto the stack frame. Before returning from the function, the function epilogue checks the guard variable to make sure that it has not been overwritten. A guard variable that is overwritten indicates a buffer overflow, and the checking code alerts the run-time environment.

Default

The default is -fno-stack-protector.

Syntax

-fstack-protector

-fstack-protector-all

-fstack-protector-strong

-fno-stack-protector

Parameters

None

Operation

-fno-stack-protector disables stack protection.

-fstack-protector enables stack protection for vulnerable functions that contain:

  • A character array larger than 8 bytes.
  • An 8-bit integer array larger than 8 bytes.
  • A call to alloca() with either a variable size or a constant size bigger than 8 bytes.

-fstack-protector-all adds stack protection to all functions regardless of their vulnerability.

-fstack-protector-strong enables stack protection for vulnerable functions that contain:

  • An array of any size and type.
  • A call to alloca().
  • A local variable that has its address taken.

Note

If you specify more than one of these options, the last option that is specified takes effect.

When a vulnerable function is called with stack protection enabled, the initial value of its guard variable is taken from a global variable:

void *__stack_chk_guard;

You must provide this variable with a suitable value. For example, a suitable implementation might set this variable to a random value when the program is loaded, and before the first protected function is entered. The value must remain unchanged during the life of the program.

When the checking code detects that the guard variable on the stack has been modified, it notifies the run-time environment by calling the function:

void __stack_chk_fail(void);

You must provide a suitable implementation for this function. Normally, such a function terminates the program, possibly after reporting a fault.

Optimizations can affect the stack protection. The following are simple examples:

  • Inlining can affect whether a function is protected.
  • Removal of an unused variable can prevent a function from being protected.

Example: Stack protection

Create the following main.c and get.c files:

// main.c
#include <stdio.h>
#include <stdlib.h>

void *__stack_chk_guard = (void *)0xdeadbeef;

void __stack_chk_fail(void)
{
    fprintf(stderr, "Stack smashing detected.\n");
    exit(1);
}

void get_input(char *data);

int main(void)
{
    char buffer[8];
    get_input(buffer);
    return buffer[0];
}
// get.c
#include <string.h>

void get_input(char *data)
{
    strcpy(data, "01234567");
}

When main.c and get.c are compiled with -fstack-protector, the array buffer is considered vulnerable and stack protection gets applied the function main(). The checking code recognizes the overflow of buffer that occurs in get_input():

armclang --target=arm-arm-none-eabi -march=armv8-a -fstack-protector main.c get.c

Running the image displays the following message:

Stack smashing detected.
Was this page helpful? Yes No