{{Header}}
{{title|title=
Compiler Hardening
}}
{{#seo:
|description=Compiler flags for hardening compiled applications at both binary and source code levels.
}}
{{coding_style_mininav}}
{{intro|
Compiler flags for hardening compiled applications at both binary and source code levels.
}}
= Introduction =
Many compilers for languages such as C have only a small subset of their available hardening and diagnostic features enabled by default. Enabling these features can help produce higher-quality code and make compiled executables much more difficult to exploit.
= C compiler flags =
For all file types built with GCC and Clang on all platforms:
* -O2
: Enables a safe level of optimizations. Improves both speed and security.
* -g
: Enables generation of debugging symbols.
* -Wall
: Enables general warnings that should be addressed in all applications.
* -Wextra
: Enables additional warnings that should be addressed in most applications.
* -Wformat -Wformat=2
: Checks calls to string formatting functions such as printf and warns if they appear malformed.
* -Wconversion
: Prints warnings when implicit type conversions may alter a value. Catches issues like attempting to store negative values in unsigned integers.
* -Wimplicit-fallthrough
: Catches instances where a switch case block falls through into the block beneath it.
* -Werror=format-security
: Disallows printf-like calls that are likely to be security holes.
* -Werror=implicit
: Disallows function declarations without a type and function calls before a function is declared.
* -Werror=int-conversion
: Disallows incompatible implicit pointer-to-integer conversions and vice versa.
* -Werror=incompatible-pointer-types
: Disallows conversion of pointers between incompatible types.
* -Wformat-overflow
: Warns when parameters to sprintf and similar may overflow the destination buffer.
* -Wformat-signedness
: Warns if an unsigned integer is passed to printf or similar when a signed integer is needed, and vice versa.
* -Wnull-dereference
: Warns if a NULL pointer dereference is detected by the compiler (note: by default this is a no-op because we use -fno-delete-null-pointer-checks).
* -Winit-self
: Warns if code attempts to initialize an uninitialized variable with itself.
* -Wmissing-include-dirs
: Warns if a user-supplied include directory does not exist.
* -Wshift-negative-value
: Warns if attempting to left-shift a negative value.
* -Wshift-overflow
: Warns if a left-shift causes an overflow in unsafe instances.
* -Wswitch-default
: Warns if a switch statement does not have a default case.
* -Wuninitialized
: Warns if an uninitialized variable is used.
* -Walloca
: Warns if the alloca
function is used. This function is unsafe because it can cause stack overflow or behave unpredictably with function arguments.
* -Warray-bounds
: Warns if an out-of-bounds array access is detected.
* -Wfloat-equal
: Warns if attempting to perform a direct equality comparison with floating-point numbers (as this is prone to errors).
* -Wshadow
: Warns if a local variable or type declaration shadows another.
* -Wpointer-arith
: Warns if performing arithmetic using the size of void or function types, which have a size of 1 counterintuitively.
* -Wundef
: Warns if an undefined identifier is evaluated in an #if directive.
* -Wunused-macros
: Warns if a macro is defined but never used.
* -Wbad-function-cast
: Warns if casting a function call to a non-matching type (e.g. casting a function pointer that returns int to one returning another pointer).
* -Wcast-qual
: Warns if a cast removes a type qualifier, such as casting const char *
to char *
.
* -Wcast-align
: Warns if a pointer cast results in possible pointer alignment issues.
* -Wwrite-strings
: Warns if a string constant's address is placed in a non-const buffer.
* -Wdate-time
: Warns if time-related macros are encountered. These break build reproducibility.
* -Wstrict-prototypes
: Warns if a function is declared or defined without specifying argument types.
* -Wold-style-definition
: Warns if using an old-style C function declaration, which is very error-prone.
* -Wredundant-decls
: Warns if the same entity is declared more than once in the same scope.
* -Winvalid-utf8
: Warns if an invalid UTF-8 character is found.
* -Wvla
: Warns if a variable-length array is used.
* -Wdisabled-optimization
: Warns if the compiler cannot optimize the code in all requested ways.
* -Wstack-protector
: Warns about functions not protected from stack smashing.
* -Wdeclaration-after-statement
: Warns if declarations occur after statements in a scope block. This encourages grouping declarations, making it easier to ensure variables are properly initialized.
* -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3
: Adds additional compile- and run-time checks for several libc functions.
* -fstack-clash-protection
: Attempts to prevent stack clash style attacks.
* -fstack-protector-all
: Protects against stack smashing in all functions.
* -fno-delete-null-pointer-checks
: Prevent the compiler from deleting explicit null pointer checks from code. This optimization is potentially very dangerous. Note that disabling this optimization also renders -Wnull-dereference
unable to warn about anything, so developers should temporarily remove it before doing test builds, then re-add it later.
* -fno-strict-aliasing
: Disables strict aliasing rules, so that casting between pointer types (e.g. from char buffer to uint64_t) is well-defined.
* -fsanitize=address,undefined
: Catches undefined behavior and invalid memory accesses.
* -fno-sanitize-recover=all
: Ensures sanitizer-detected bugs terminate the program.
* -fstrict-flex-arrays=3
: Only treats a trailing array in a struct as flexible if defined with no specified length.
* -ftrivial-auto-var-init=pattern
: Ensure stack-allocated variables are virtually always initialized, using a special pattern that will probably cause a crash if the variable isn't intentionally initialized. This both mitigates security issues resulting from uninitialized variables, and makes it easier to catch bugs resulting from them.
* -Wl,-z,nodlopen
: Disallows dlopen'ing of the compiled objects.
* -Wl,-z,noexecstack
: Marks compiled objects as not requiring an executable stack.
* -Wl,-z,relro -Wl,-z,now
: Resolves all symbols when the program is loaded and then makes the global offset table read-only, thwarting GOT overwrite attacks.
* -Wl,--as-needed
: Links only libraries that are actually used, reducing attack surface.
* -Wl,--no-copy-dt-needed-entries
: Prevents libraries from pulling in unneeded dependencies. All needed libraries must be explicitly specified.
For all file types built with GCC only, not supported by Clang:
* -Wtrampolines
: Warns if GCC creates trampoline code on the stack, which often requires an executable stack.
* -Wbidi-chars=any,ucn
: Warns if bidirectional control characters or UCN codes are used. These can be used for trojan source attacks.
* -Wformat-overflow=2
: Performs deeper analysis to detect format overflow bugs.
* -Wformat-truncation=2
: Warns if a printf-like call is likely to truncate output, even when the return value is used.
* -Wshift-overflow=2
: Warn if a left shift could be unsafe, even if a 1 is being left-shifted into the sign bit (something plain -Wshift-overflow
does not catch).
* -Wtrivial-auto-var-init
: Warns if a stack-allocated variable cannot be automatically initialized (e.g. in switch blocks before the first case statement).
* -Wstringop-overflow=3
: Performs paranoid-level checks for memory copy overflows.
* -Wstrict-flex-arrays
: Warns if code appears to misuse an array at the end of a struct as a flexible array member.
* -Walloc-zero
: Warns if attempting to allocate a zero-size buffer.
* -Warray-bounds=2
: Performs paranoid-level checks for out-of-bounds array accesses.
* -Wattribute-alias=2
: Warns if a function alias has incompatible or more restrictive attributes than the function it aliases.
* -Wduplicated-branches
: Warns if both branches of an if/else perform the same action.
* -Wduplicated-cond
: Warns if the same condition appears multiple times in an if-else-if chain.
* -Wcast-align=strict
: Warns about potential alignment issues from casts, even on CPUs where alignment may not matter. This likely helps catch bugs that only will strike some CPUs even if we aren't building for those CPUs.
* -Wjump-misses-init
: Warns if a jump skips over or duplicates a variable initialization.
* -Wlogical-op
: Warns about suspicious logical operator use (e.g. when a bitwise operator was likely intended).
For all file types built with GCC and Clang, x86_64 only:
* -fcf-protection=full
: Enables full control-flow protection.
For all file types built with GCC and Clang, aarch64 only:
* -mbranch-protection=standard
: Enables all branch protection features.
For executables built with GCC and Clang, not libraries:
* -fPIE
: Generates position-independent executable code.
* -pie
: Creates a position-independent executable.
For libraries built with GCC and Clang, not executables:
* -fPIC
: Generates position-independent library code.
All flags for GCC x86_64 executables:
{{CodeSelect|code=
-O2 -g -Wall -Wextra -Wformat -Wformat=2 -Wconversion -Wimplicit-fallthrough \
-Werror=format-security -Werror=implicit -Werror=int-conversion \
-Werror=incompatible-pointer-types -Wformat-overflow -Wformat-signedness \
-Wnull-dereference -Winit-self -Wmissing-include-dirs -Wshift-negative-value \
-Wshift-overflow -Wswitch-default -Wuninitialized -Walloca -Warray-bounds \
-Wfloat-equal -Wshadow -Wpointer-arith -Wundef -Wunused-macros \
-Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wdate-time \
-Wstrict-prototypes -Wold-style-definition -Wredundant-decls -Winvalid-utf8 \
-Wvla -Wdisabled-optimization -Wstack-protector -Wdeclaration-after-statement \
-Wtrampolines -Wbidi-chars=any,ucn -Wformat-overflow=2 -Wformat-truncation=2 \
-Wshift-overflow=2 -Wtrivial-auto-var-init -Wstringop-overflow=3 \
-Wstrict-flex-arrays -Walloc-zero -Warray-bounds=2 -Wattribute-alias=2 \
-Wduplicated-branches -Wduplicated-cond -Wcast-align=strict \
-Wjump-misses-init -Wlogical-op -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 \
-fstack-clash-protection -fstack-protector-all \
-fno-delete-null-pointer-checks -fno-strict-aliasing \
-fsanitize=address,undefined -fno-sanitize-recover=all -fstrict-flex-arrays=3 \
-ftrivial-auto-var-init=pattern -fcf-protection=full -fPIE -Wl,-z,nodlopen \
-Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--as-needed \
-Wl,--no-copy-dt-needed-entries -pie
}}
All flags for Clang x86_64 executables:
{{CodeSelect|code=
-O2 -g -Wall -Wextra -Wformat -Wformat=2 -Wconversion -Wimplicit-fallthrough \
-Werror=format-security -Werror=implicit -Werror=int-conversion \
-Werror=incompatible-pointer-types -Wformat-overflow -Wformat-signedness \
-Wnull-dereference -Winit-self -Wmissing-include-dirs -Wshift-negative-value \
-Wshift-overflow -Wswitch-default -Wuninitialized -Walloca -Warray-bounds \
-Wfloat-equal -Wshadow -Wpointer-arith -Wundef -Wunused-macros \
-Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wdate-time \
-Wstrict-prototypes -Wold-style-definition -Wredundant-decls -Winvalid-utf8 \
-Wvla -Wdisabled-optimization -Wstack-protector -Wdeclaration-after-statement \
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -fstack-clash-protection \
-fstack-protector-all -fno-delete-null-pointer-checks -fno-strict-aliasing \
-fsanitize=address,undefined -fno-sanitize-recover=all -fstrict-flex-arrays=3 \
-ftrivial-auto-var-init=pattern -fcf-protection=full -fPIE -Wl,-z,nodlopen \
-Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--as-needed \
-Wl,--no-copy-dt-needed-entries -pie
}}
= See Also =
* [[Dev/bash]]
* [[Dev/coding style]]
{{Footer}}
[[Category: Design]]