AD3011: EnableBindNow¶
Summary¶
| Property | Value |
|---|---|
| ID | AD3011 |
| Name | EnableBindNow |
| Category | Security |
| Severity | Error |
| Applies to | ELF (Linux/Unix) |
Description¶
BIND_NOW causes the dynamic linker to resolve all symbols at program startup rather than lazily on first use. Combined with Relocation Read-Only (RELRO), this enables Full RELRO protection where the entire Global Offset Table (GOT) is made read-only after startup.
How It Works¶
The rule checks for the BIND_NOW flag or NOW flag in the dynamic section:
- Checks
DT_FLAGSforDF_BIND_NOW - Checks
DT_FLAGS_1forDF_1_NOW - Either flag indicates immediate binding
Why This Matters¶
BIND_NOW is the missing piece of Full RELRO protection. Without it, the GOT remains writable for lazy symbol resolution, leaving a window of vulnerability that attackers can exploit.
The Lazy Binding Problem¶
Lazy binding is designed for performance but creates security issues:
With Lazy Binding:
Program starts → GOT contains PLT stubs
First call to printf() → Dynamic linker resolves
GOT[printf] updated to real address
PROBLEM: GOT must remain writable!
With BIND_NOW:
Program starts → All symbols resolved
GOT filled with real addresses
GOT marked read-only immediately
RESULT: No window of vulnerability
Attack Window¶
| Phase | Lazy Binding | BIND_NOW |
|---|---|---|
| Before first call | GOT writable | GOT read-only |
| After first call | Still writable | Still read-only |
| After all calls | Still writable | Still read-only |
Security Benefits¶
Lazy binding attack:
1. Exploit vulnerability (format string, overflow)
2. Overwrite GOT entry before function is called
3. Wait for legitimate code to call function
4. Control flow hijacked!
With BIND_NOW:
1. Exploit vulnerability
2. Try to overwrite GOT entry
3. SIGSEGV - GOT is read-only!
4. Attack fails
Startup Time Trade-off¶
| Application Type | Symbol Count | Startup Impact |
|---|---|---|
| Simple CLI | ~50 | <1ms |
| Complex app | ~500 | ~5ms |
| Large GUI app | ~2000 | ~20ms |
| Heavy linking | ~10000 | ~100ms |
For long-running services, startup time is negligible compared to uptime.
Early Failure Detection¶
BIND_NOW also catches missing symbols immediately:
Lazy binding:
- Missing symbol: crash on first use
- Might not be discovered until rare code path
- Production failure possible
BIND_NOW:
- Missing symbol: crash at startup
- Immediate detection
- Testing catches the problem
Combining with RELRO¶
| Configuration | GOT Protection |
|---|---|
| Neither | None |
| RELRO only | Partial (.got protected, .got.plt writable) |
| BIND_NOW only | None (no RELRO marking) |
| RELRO + BIND_NOW | Full (entire GOT read-only) |
Always use both flags together for maximum protection.
Environment Variable Alternative¶
# Force BIND_NOW at runtime (for testing)
LD_BIND_NOW=1 ./program
# But compile-time flag is more reliable
gcc -Wl,-z,now program.c -o program
- Full RELRO: Enables complete GOT protection
- Predictable behavior: All symbols resolved at startup
- Early failure: Missing symbols caught immediately
- Exploit mitigation: GOT is read-only after startup
Lazy vs Immediate Binding¶
Lazy Binding (Default)¶
Startup: Minimal work
First call to printf() → resolve printf → call printf
First call to malloc() → resolve malloc → call malloc
GOT entries writable until resolved
Immediate Binding (BIND_NOW)¶
Startup: Resolve all symbols
printf() → already resolved
malloc() → already resolved
GOT can be marked read-only immediately
Resolution¶
GCC/Clang¶
# Enable BIND_NOW
gcc -Wl,-z,now source.c -o binary
# Full RELRO (RELRO + BIND_NOW)
gcc -Wl,-z,relro -Wl,-z,now source.c -o binary
CMake¶
Makefile¶
Environment Variable¶
Force for any program:
When to Suppress¶
This rule may be suppressed for:
- Large applications: Many symbols = longer startup
- Plugin architectures: dlopen() heavy applications
- Startup-sensitive: Where latency matters
- Resource-constrained: Limited memory for eager loading
Caveats¶
- Increases startup time proportional to symbol count
- All dependencies loaded at startup
- May use more memory at startup
- Some applications with many plugins may see significant impact
Performance Considerations¶
| Application Type | Impact | Recommendation |
|---|---|---|
| CLI tools | Minimal | Enable |
| Daemons | One-time cost | Enable |
| Short-lived processes | May be noticeable | Consider |
| Plugin-heavy apps | Potentially significant | Measure first |