Skip to content

AD3016: EnableIntelShadowStack

Summary

Property Value
ID AD3016
Name EnableIntelShadowStack
Category Security
Severity Warning
Applies to ELF (Linux/Unix) - x86_64

Description

This rule checks that x86_64 ELF binaries have Intel Shadow Stack (SHSTK) enabled as part of Control-flow Enforcement Technology (CET). Shadow Stack protects against Return-Oriented Programming (ROP) attacks by maintaining a hardware-protected copy of return addresses.

Why This Matters

Intel Shadow Stack provides the most robust defense against ROP attacks available today. By maintaining a hardware-protected copy of return addresses, it makes ROP exploitation extremely difficult even with full memory corruption.

The ROP Problem

Return-Oriented Programming has dominated exploitation for over a decade:

Classic ROP:
  1. Overflow buffer, overwrite return address
  2. Chain "gadgets" (code sequences ending in RET)
  3. Each RET pops next gadget address from stack
  4. Achieve arbitrary computation
  5. Stack canaries? Bypassed if leak exists.
  6. ASLR? Bypassed with info leak.

How Shadow Stack Defeats ROP

With Shadow Stack:
  1. CALL pushes return address to BOTH stacks
  2. Attacker overwrites return address on normal stack
  3. RET pops from normal stack (corrupted)
  4. CPU compares with shadow stack (clean)
  5. MISMATCH! #CP exception
  6. Attack defeated

Shadow Stack Protection Properties

Property Benefit
Separate memory region Not adjacent to corruptible data
Hardware-protected Normal instructions can't write
Per-thread Each thread has own shadow stack
CPU-managed No software overhead for checks

What Attackers Would Need

To bypass Shadow Stack, attackers would need to:

1. Find ROP gadgets (still possible with IBT off)
2. Write exploit (harder - return addresses protected)
3. Either:
   a. Corrupt shadow stack (requires hardware bug)
   b. Use only non-RET gadgets (JOP - but IBT stops this)
   c. Find oracle to leak shadow stack location

Performance Characteristics

Operation Overhead
CALL instruction ~1 cycle (parallel push)
RET instruction ~1 cycle (parallel compare)
Overall application 0-2% measured

Hardware implementation means near-zero overhead.

Combining IBT and Shadow Stack

Protection Attack Prevented
IBT only JOP, COP
Shadow Stack only ROP
Both (full CET) ROP, JOP, COP

Full CET (-fcf-protection=full) provides comprehensive control-flow protection.

OS Support Status

OS Shadow Stack Support
Linux 5.6+ Kernel support
Linux 6.6+ Improved userspace
Windows 10 20H1+ Full support
Windows 11 Enabled by default
  • ROP protection: Shadow Stack detects corrupted return addresses
  • Hardware enforcement: The CPU maintains a separate, protected stack for return addresses
  • Tamper-resistant: The shadow stack cannot be modified by normal instructions
  • Low overhead: Hardware implementation has minimal performance impact

Performance Considerations

Intel Shadow Stack is hardware-accelerated with near-zero overhead:

Metric Impact
Per CALL overhead ~1 cycle (parallel push)
Per RET overhead ~1 cycle (parallel compare)
Overall application 0-2% measured
Memory overhead Small shadow stack per thread

Why overhead is minimal: - Hardware maintains shadow stack in parallel with normal execution - No software instrumentation needed - Shadow stack operations happen during existing CALL/RET cycles

Measured overhead:

Workload Overhead
SPEC CPU 2017 ~1% average
Server workloads <1%
Call-heavy code 1-2%

Combined with IBT: Full CET (-fcf-protection=full) enables both IBT and Shadow Stack with approximately 1-2% combined overhead.

How Shadow Stack Works

  1. On CALL, the return address is pushed to both the regular stack and the shadow stack
  2. On RET, the CPU compares the return address from both stacks
  3. If they differ, a control protection fault (#CP) is raised
  4. Attackers cannot overwrite shadow stack entries to perform ROP

How to Fix

Compile with CET enabled

# Enable both IBT and Shadow Stack
gcc -fcf-protection=full -o myapp myapp.c

# Enable Shadow Stack only
gcc -fcf-protection=return -o myapp myapp.c
# Ensure linker supports CET
ld --version  # Should be binutils 2.31+

Verify the fix

readelf -n myapp | grep -i "SHSTK"
# Should show: Properties: x86 feature: IBT, SHSTK

Example

Fail: Binary does not have Shadow Stack enabled

Properties: x86 ISA needed: x86-64-baseline

Pass: Binary has Shadow Stack enabled

Properties: x86 feature: IBT, SHSTK

Requirements

  • Compiler: GCC 8+ or Clang 7+
  • CPU: Intel Tiger Lake+, AMD Zen 3+
  • Kernel: Linux 6.6+ for full userspace shadow stack support
  • glibc: 2.39+ for full support

See Also