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:
__safestack_initsymbol presence__safestack_unsafe_stack_ptrthread-local variable- 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: