difference between gcc -D_FORTIFY_SOURCE=1 and -D_FORTIFY_SOURCE=2
SecurityGccGlibcSecurity Problem Overview
Can someone point out the difference between gcc -D_FORTIFY_SOURCE=1
and -D_FORTIFY_SOURCE=2
? I guess =2
is more secure? I haven't been able to find a list which lists differences point by point.
I have also read that -D_FORTIFY_SOURCE=2
should be used with -O2
, otherwise not all features would be available. Also here i haven't found a list which would specify the regressions in detail. I would especially be interested to compile with -Os
as the target is a device with not so much flash memory.
Any hints on where this is documented welcome!
Security Solutions
Solution 1 - Security
From the manual page for the Feature Test Macros (man 7 feature_test_macros
)
> ### _FORTIFY_SOURCE
(since glibc 2.3.4)
>
> Defining this macro causes some lightweight checks to be performed to detect some buffer overflow errors when employing various string and memory manipulation functions (for example, memcpy
, memset
, stpcpy
, strcpy
, strncpy
, strcat
, strncat
, sprintf
, snprintf
, vsprintf
, vsnprintf
, gets
, and wide character variants thereof). For some functions, argument consistency is checked; for example, a check is made that open
has been supplied with a mode argument when the specified flags include O_CREAT
. Not all problems are detected, just some common cases.
>
> If _FORTIFY_SOURCE
is set to 1, with compiler optimization level 1 (gcc -O1
) and above, checks that shouldn't change the behavior of conforming programs are performed.
>
> With _FORTIFY_SOURCE
set to 2, some more checking is added, but some conforming programs might fail.
>
> Some of the checks can be performed at compile time (via macros logic implemented in header files), and result in compiler warnings; other checks take place at run time, and result in a run-time error if the check fails.
>
> Use of this macro requires compiler support, available with gcc
since version 4.0.
Moreover, the article Enhance application security with FORTIFY_SOURCE (March 2014) says:
gcc -D_FORTIFY_SOURCE=1
adds checks at compile-time only (some headers are necessary as#include <string.h>
)gcc -D_FORTIFY_SOURCE=2
also adds checks at run-time (detected buffer overflow terminates the program)
Essentially, _FORTIFY_SOURCE
level 2 is more secure, but is a slightly riskier compilation strategy; if you use it, make sure you have very strong regression tests for your compiled code to prove the compiler hasn't introduced any unexpected behaviour.
Solution 2 - Security
http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html goes into more detail than feature_test_macros(7)
.
Here's the relevant excerpt, lightly edited/reformatted for clarity:
> The difference between -D_FORTIFY_SOURCE=1
and -D_FORTIFY_SOURCE=2
> is e.g. for
>
> struct S {
> struct T {
> char buf[5];
> int x;
> } t;
> char buf[20];
> } var;
>
> With -D_FORTIFY_SOURCE=1
,
>
> strcpy (&var.t.buf[1], "abcdefg");
>
> is not considered an overflow (object is whole var
), while
> with -D_FORTIFY_SOURCE=2
>
> strcpy (&var.t.buf[1], "abcdefg");
>
> will be considered a buffer overflow.
>
> Another difference is that with -D_FORTIFY_SOURCE=2
, %n
> in format strings of the most common *printf
family functions
> is allowed only if it is stored in read-only memory (usually
> string literals, gettext
's _("%s string %n")
is fine too), but
> usually when an attacker attempts to exploit a format string
> vulnerability, %n
will be somewhere where the attacker could
> write it into.