My old fossilized reference can still be found at https://gist.github.com/hed0rah/f5c976fdc602688a0fd40288fde6d886
Modern GCC hardening reference for production builds and security testing.
CFLAGS="-fhardened -O2"
LDFLAGS=""-fhardened is a bundled hardening profile intended for production use.
Typically enables:
-fstack-protector-strong-fstack-clash-protection-fcf-protection=full(x86 systems)-D_FORTIFY_SOURCE=3(falls back if required by libc)-D_GLIBCXX_ASSERTIONS-fPIE -pie
Notes:
- Exact contents can vary by GCC version and target architecture.
- Intended for GNU/Linux targets.
- Preferred over manually assembling flag sets when available.
CFLAGS="-O2 \
-fPIE \
-fstack-protector-strong \
-fstack-clash-protection \
-D_FORTIFY_SOURCE=3"
LDFLAGS="-pie -Wl,-z,relro,-z,now"Adds stack canaries to functions considered likely attack targets:
- Local arrays
- Address-taken variables
alloca()use
Recommended balance between protection and overhead.
Protect every function regardless of risk profile.
Useful when policy requires complete coverage, but usually unnecessary.
Warn if functions are not protected.
Protect against stack-clash attacks where large stack growth skips over guard pages.
Low overhead and commonly enabled.
Enable Intel CET support where available:
- IBT — Indirect Branch Tracking
- SHSTK — Shadow Stack
Requirements:
- Supported CPU
- Kernel support
- Userspace support
Adds compile-time and runtime validation for common libc functions:
Examples:
memcpy()strcpy()snprintf()printf()
Requirements:
-O1or higher optimization.
Version 3 expands coverage beyond older =2 behavior.
Enables Full RELRO
Effects:
- Resolves symbols at startup
- Makes relocation structures read-only
- Prevents many GOT overwrite attacks
Produces position-independent executables.
Required for executable ASLR.
These improve code quality and bug detection but are not direct exploit mitigations.
-Wall -WextraEnables broad sets of useful warnings.
Important: -Wall does not mean "all warnings."
-Wconversion
-Wsign-conversionWarn on implicit conversions that may lose information.
-Wformat
-Wformat-securityDetect potentially dangerous printf() patterns.
-WshadowDetect accidental variable hiding.
-WerrorTreat warnings as errors.
Useful in CI and for preventing warning regressions.
Traps signed integer overflow.
May introduce substantial overhead because GCC can emit helper function calls.
-fsanitize=signed-integer-overflow
-fsanitize-undefined-trap-on-errorUsually emits efficient inline overflow checks.
Do not typically enable these in production builds.
-fsanitize=addressDetects:
- Heap overflows
- Stack overflows
- Use-after-free
- Use-after-return
- Double free
Typical cost:
- ~2× memory
- ~1.5–3× runtime
-fsanitize=undefinedDetects:
- Signed overflow
- Invalid shifts
- Alignment violations
- Null dereferences
- Various undefined behavior
Can log or trap depending on configuration.
-fsanitize=threadDetects:
- Data races
Typical cost:
- ~5–15× runtime
Notes:
- Cannot be combined with ASan
-fsanitize=leakDetects:
- Memory leaks
Often integrated automatically with ASan on Linux.
Avoid Procedure Linkage Table stubs for external calls.
Effects:
- Small performance gain
- Slightly reduced attack surface
Enable additional runtime checks for:
- STL containers
- Iterators
- Bounds-related issues
Low overhead and commonly worthwhile.
CFLAGS="-O2 -fhardened"
LDFLAGS=""CFLAGS="-O2 \
-fPIE \
-fstack-protector-strong \
-fstack-clash-protection \
-D_FORTIFY_SOURCE=3"
LDFLAGS="-pie -Wl,-z,relro,-z,now"CFLAGS="-O1 -g \
-fsanitize=address \
-fsanitize=undefined"
LDFLAGS="-fsanitize=address \
-fsanitize=undefined"