ASLR randomizes where the stack, heap and shared libraries sit in memory, and PIE extends that to the program's own code. Together they stop a memory corruption bug from relying on fixed addresses. They raise the cost of exploitation, but they do not fix the bug, so you still need to patch it.
What does ASLR do?
Address space layout randomization changes memory locations on each run. The Linux kernel documents this through the randomize_va_space setting. Value 0 turns randomization off. Value 1 randomizes the mmap base, stack and VDSO page, which implies shared libraries load at random addresses, and for PIE linked binaries the code start is randomized too. Value 2 adds heap randomization. The kernel notes that value 2 is the default when the CONFIG_COMPAT_BRK option is disabled, and that a few legacy applications assume a fixed heap start.
The point is simple. A stack overflow lets an attacker overwrite saved control data. Without randomization, the destination addresses they would jump to are the same every time. With it, an attacker also needs a way to learn an address first, which usually means a second bug such as an information leak.
What does PIE add?
Without position independent executables, the main program loads at a fixed address even when libraries are randomized. Fixed code addresses give an attacker a stable place to point. Building as PIE lets the loader place the program at a random base as well. The gain is that the program's own code stops being a fixed target.
What about the other hardening flags?
Three more build settings pair with ASLR.
A stack protector places a check value, often called a canary, before saved return data and verifies it before returning, so a simple linear overflow is caught.
Non executable stack and heap keep injected data from running as code.
Full RELRO makes relocation tables read only after startup, which removes a classic target for overwriting.
Each setting blocks a different step. None is complete on its own, which is why the standard advice is to enable all of them.
Why do they not make a bug safe?
Defenses that depend on secrets, such as an address or a canary value, fail if the secret leaks. Information disclosure bugs are common enough that mitigations are treated as speed bumps. The only durable fix is removing the bug, or choosing a memory safe language for new components. CISA's secure by design guidance, updated in October 2023 with international partners, pushes manufacturers towards taking ownership of customer security outcomes, which includes eliminating classes of bugs.
A constructed example
A team ships a small network daemon written in C. A review shows it was built without PIE and the container image runs on a host where randomize_va_space is set to 0 for a debugging session long ago. Both are fixed in an hour: the build gains the PIE and stack protector flags, and the host setting returns to 2. The team also schedules a fuzzing run and a code review of the parser, since hardening only reduces damage.
How to check or apply this
- On Linux hosts, read the randomize_va_space value and confirm it is 2.
- Use a checking tool such as checksec or readelf on your binaries to see whether PIE, stack protector and full RELRO are present.
- Add the matching compiler and linker flags to your build, and fail the build if they are missing.
- Run containers on hosts you control or know the kernel settings of.
- Fuzz and review code that parses untrusted input.
- For new code, consider a memory safe language.
Safeguard's SAST code scan can flag unsafe patterns in source, and dependency scanning covers vulnerable native libraries you link against.
Quick check
Does ASLR prevent buffer overflows?
No. It makes exploiting them harder by hiding addresses. The overflow itself is still a bug that needs fixing.
What does randomize_va_space set to 2 mean?
Full randomization on Linux: mmap base, stack, VDSO and PIE code start, plus the heap.
Sources
Last reviewed: 18 October 2026.