Thursday, May 31, 2018

Protecting against buffer overflows (using gcc)

We try our best to avoid buffer overflows, but still it is possible that one creeps into our code. When this happens, there are some gcc compiler options and macros that we can use to protect our program from buffer overflow exploits.
Sometimes these features may be enabled by default. But this has not been the case for the cross toolchains that I have used.
  • -fstack-protector gcc option and its variants
    • Works by placing a small integer, the value of which is randomly chosen at program start, in memory just before the stack return pointer (stack canaries)
    • Attacker has to write past this value to run his code using a buffer overflow attack
    • Applicable only to stack (not heap)
    • When detected, aborts the program
      *** stack smashing detected ***: ./overflow terminated
       Aborted
    • Chooses any function that declares a character array of eight bytes or more in length on its stack  
    • -fstack-protector-all is similar to -fstack-protector, but applied to every function
    • This option comes with a cost on program size and performance
    • See "Strong" stack protection for GCC LWN article for more details
  • _FORTIFY_SOURCE macro
    • Defining this macro causes some lightweight checks to be performed to detect some buffer overflow errors when employing various string and memory manipulation functions. See feature test macros for more details.
      e.g. When this is defined, instead of calling memcpy, it will call a object size checking function __builtin___memcpy_chk
    • Need to enable optimization to define this
      e.g. gcc -D_FORTIFY_SOURCE=1 -O0 -o overflow overflow_test.c
      will say
      #  warning _FORTIFY_SOURCE requires compiling with optimization (-O)
    • Can detect both stack and heap buffer overflows
    • When detected, aborts the program
      *** buffer overflow detected ***: ./overflow terminated
      Aborted