Skip to content

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:

  1. Checks DT_FLAGS for DF_BIND_NOW
  2. Checks DT_FLAGS_1 for DF_1_NOW
  3. 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

add_link_options(-Wl,-z,now)

# Full RELRO
add_link_options(-Wl,-z,relro -Wl,-z,now)

Makefile

LDFLAGS += -Wl,-z,now

Environment Variable

Force for any program:

LD_BIND_NOW=1 ./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

Combined with RELRO

# Both flags for full protection
gcc -Wl,-z,relro -Wl,-z,now source.c -o binary

References