Skip to content

AD2038: PeEnableClangSafeStack

Summary

Property Value
ID AD2038
Name PeEnableClangSafeStack
Category Security
Severity Warning
Applies to PE (Windows, Clang compiled)

Description

PE binaries compiled with Clang should consider enabling SafeStack to provide architectural protection against stack buffer overflows.

How It Works

The rule checks for SafeStack indicators:

  1. __safestack_init symbol presence
  2. __safestack_unsafe_stack_ptr thread-local variable
  3. SafeStack-related runtime symbols

Why This Matters

SafeStack provides stronger protection than stack canaries by physically separating vulnerable stack data from return addresses.

SafeStack Architecture

Traditional Stack:        SafeStack:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       Safe Stack:     Unsafe Stack:
β”‚ Return Address  β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€       β”‚ Ret Addr  β”‚   β”‚ char buf[]   β”‚
β”‚ Saved RBP       β”‚       β”‚ Saved RBP β”‚   β”‚ Local arrays β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€       β”‚ Safe vars β”‚   β”‚ Addr-taken   β”‚
β”‚ char buffer[64] β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ Other locals    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       Separate memory regions!

Security Comparison

Protection Canary SafeStack
Detection After-the-fact Architectural
Bypassable Info leak No
Performance Check overhead Minimal
Return address Can be corrupted Physically protected

Windows Considerations

SafeStack on Windows requires:

Requirement Notes
Clang compiler Not available in MSVC
TLS support For unsafe stack pointer
Runtime init SafeStack runtime

Performance Considerations

SafeStack has low overhead, making it suitable for production:

Metric Impact
Runtime overhead 1-5% typical
Memory overhead ~2x stack space
Code size Minimal increase

Comparison with alternatives:

Protection Overhead Security
Stack canaries <1% Detects after corruption
SafeStack 1-5% Prevents corruption
ASAN 100-200% Testing only

Why SafeStack is efficient:

  • Only unsafe variables (buffers, address-taken) move to unsafe stack
  • Safe variables stay on the normal stack
  • No runtime checks neededβ€”protection is architectural

Workload impact:

Workload Overhead
Compute-bound <1%
Buffer-heavy 2-5%
Call-intensive 1-3%

Resolution

Enable SafeStack when building with Clang:

clang-cl -fsanitize=safe-stack program.c

CMake Configuration

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    target_compile_options(myapp PRIVATE -fsanitize=safe-stack)
    target_link_options(myapp PRIVATE -fsanitize=safe-stack)
endif()