AD3014: NoTextRelocations¶
Summary¶
| Property | Value |
|---|---|
| ID | AD3014 |
| Name | NoTextRelocations |
| Category | Correctness |
| Severity | Error |
| Applies to | ELF (Linux/Unix) |
Description¶
This rule checks that ELF binaries do not contain text relocations (TEXTREL). Text relocations require the .text (code) section to be writable during loading, which defeats W^X (Write XOR Execute) memory protections.
Why This Matters¶
Text relocations fundamentally break the W^X (Write XOR Execute) security model. When code must be writable, it becomes trivially exploitable—and the system loses one of its most important defenses.
What Are Text Relocations?¶
When code contains absolute addresses that must be adjusted at load time:
// Absolute address compiled into code:
movq $0x12345678, %rax // Points to global variable
// At load time, linker must patch this address
// Requires .text section to be WRITABLE
The W^X Violation¶
Normal memory layout:
.text - Readable, Executable (not writable)
.data - Readable, Writable (not executable)
With TEXTREL:
.text - Readable, Writable, Executable
= Attackers can inject code
Security Implications¶
| Attack | Without TEXTREL | With TEXTREL |
|---|---|---|
| Code injection | Blocked (W^X) | Possible |
| GOT overwrite + ret2text | Complex | Easier |
| Exploit reliability | Lower | Higher |
Performance Impact¶
TEXTREL prevents code sharing:
Without TEXTREL:
Process A: Maps libc.so at 0x7fff1000
Process B: Maps same pages (shared memory)
Memory: 1 copy of libc code
With TEXTREL:
Process A: Loads libc.so, patches addresses
Process B: Must have own copy (different patches)
Memory: Multiple copies of libc code
Hardened System Rejection¶
Many security-focused environments reject TEXTREL:
| System | TEXTREL Handling |
|---|---|
| SELinux (strict) | Denied, won't load |
| grsecurity | Denied by default |
| Android | Rejected for NDK |
| Hardened Gentoo | Compile error |
| OpenBSD | Warnings, may reject |
Common Causes and Fixes¶
| Cause | Fix |
|---|---|
| Non-PIC shared library | Compile with -fPIC |
| Assembly with absolute addresses | Use RIP-relative |
| Inline assembly | Use proper constraints |
| Old precompiled objects | Recompile from source |
Detecting Text Relocations¶
# Check for TEXTREL tag
readelf -d binary | grep TEXTREL
# Find which object files cause it
scanelf -qT binary
# Detailed relocation info
readelf -r binary | grep -E 'R_X86_64_32|R_386_32'
- Security: Writable code sections can be exploited for code injection attacks
- Performance: Text relocations prevent code sharing between processes
- RELRO incompatibility: Text relocations are incompatible with full RELRO protection
- SELinux/hardened kernels: Many secure systems reject binaries with text relocations
Common Causes¶
- Non-PIC code in shared libraries: Code compiled without
-fPIC - Assembly code: Hand-written assembly without proper addressing
- Old/legacy code: Code written before PIE/PIC was standard
How to Fix¶
Compile with position-independent code¶
# For shared libraries
gcc -fPIC -shared -o libexample.so example.c
# For executables (PIE)
gcc -fPIE -pie -o myapp myapp.c
Fix assembly code¶
Use PC-relative addressing or GOT-relative addressing in assembly:
# Bad: absolute address
movq $my_global, %rax
# Good: RIP-relative (x86_64)
leaq my_global(%rip), %rax
Verify the fix¶
Example¶
Fail: Binary has text relocations
Pass: No TEXTREL entry in dynamic section