30. Hardening: compiler flags, canaries, ASLR, _FORTIFY_SOURCE
clang -std=c17 -O2 \
-D_FORTIFY_SOURCE=2 \
-fstack-protector-strong \
-fPIE -pie \
-Wl,-z,relro,-z,now \
-o hardened_app app.c
The linker flags above are for Linux/ELF toolchains. On macOS or Windows,
use the platform's equivalent hardening options instead of copying the
-Wl,-z,... part verbatim.
| Flag | Defense |
|---|---|
-D_FORTIFY_SOURCE=2 |
Adds runtime bounds checks to memcpy/strcpy/sprintf/etc. when the compiler can determine the destination size — turns some overflows into an immediate abort instead of silent corruption |
-fstack-protector-strong |
Inserts a random "canary" value before the return address; if a buffer overflow overwrites it, the program detects the corruption before returning and aborts |
-fPIE -pie |
Position-independent executable — required for ASLR (address space layout randomization) to randomize the binary's own load address, not just libraries |
-Wl,-z,relro,-z,now |
Makes the GOT (global offset table) read-only after startup, closing off a common exploit technique (GOT overwrite) |
Real-world example. These are representative of the hardening options Linux distributions such as Debian, Fedora, and Ubuntu enable through their package build systems. They are not magic, but they often turn some memory-corruption bugs from "attacker gets control" into "process aborts."