AD3032: EnableSpeculativeLoadHardening¶
Summary¶
| Property | Value |
|---|---|
| ID | AD3032 |
| Name | EnableSpeculativeLoadHardening |
| Category | Security |
| Severity | Warning |
| Applies to | ELF (Linux) - x86/x86_64 binaries |
Description¶
Speculative Load Hardening (-mspeculative-load-hardening) is a Clang/LLVM mitigation that helps protect against Spectre variant 1 attacks. It works by inserting instructions that mask the result of conditional branches, preventing speculative execution from accessing sensitive data.
How It Works¶
The rule examines the ELF binary for:
- DWARF debug info with
-mspeculative-load-hardeningflag - Symbols associated with speculative load hardening
When enabled, the compiler: - Tracks branch conditions through speculative execution - Masks values that might be used speculatively - Prevents speculative memory accesses from leaking data
Why This Matters¶
Spectre variant 1 attacks exploit CPU speculative execution to leak sensitive data across security boundaries. Speculative Load Hardening prevents speculative execution from accessing data that would not be accessed in normal execution, closing this side channel.
The Spectre v1 Attack¶
// Bounds Check Bypass (Spectre v1)
if (x < array1_size) { // Branch predictor may mispredict
y = array2[array1[x] * 256]; // Speculatively executed!
}
// What happens:
// 1. Attacker trains branch predictor to predict "taken"
// 2. Attacker provides x >= array1_size
// 3. CPU predicts branch taken, speculatively executes body
// 4. array1[x] reads out-of-bounds (secret data!)
// 5. array2 access changes cache state based on secret
// 6. CPU realizes misprediction, rolls back
// 7. BUT: cache state not rolled back!
// 8. Attacker measures cache timing to extract secret
Why It's Dangerous¶
| Spectre Property | Implication |
|---|---|
| Hardware bug | Software must mitigate |
| Affects all modern CPUs | Universal vulnerability |
| Side-channel based | Hard to detect |
| Crosses boundaries | Kernel, browser, VM escapes |
How Speculative Load Hardening Works¶
Without SLH:
if (x < size) {
secret = array[x]; // Speculatively executed with bad x
}
With SLH:
if (x < size) {
mask = (x < size) ? ~0 : 0; // Tracks branch state
secret = array[x & mask]; // Masked if speculating wrong path
}
If speculating wrong path: mask = 0, array[0] accessed (not secret)
Performance Considerations¶
| Workload Type | Overhead |
|---|---|
| Compute-bound | 10-20% |
| Memory-bound | 20-40% |
| I/O-bound | Low |
| Overall average | 15-30% |
SLH has significant overhead. Use for sensitive code.
When to Enable SLH¶
Critical (enable): - Cryptographic code - Authentication systems - Multi-tenant cloud (VMs, containers) - Kernel/hypervisor code - Code with security boundaries
Lower priority: - Single-tenant applications - Non-sensitive batch processing - Where performance is critical and data is public
Comparison with Other Spectre Mitigations¶
| Mitigation | Target | Overhead | Scope |
|---|---|---|---|
| SLH | Spectre v1 | High | Per-binary |
| LFENCE | Spectre v1 | Varies | Manual insertion |
| Retpoline | Spectre v2 | Low-Medium | Indirect branches |
| STIBP/IBPB | Spectre v2 | Low | CPU feature |
Alternative Approaches¶
# Manual LFENCE insertion (lower overhead, manual effort)
asm volatile("lfence" ::: "memory");
# Compiler barrier (not sufficient alone)
asm volatile("" ::: "memory");
SLH automates the protection at the cost of higher overhead.
Spectre variant 1 attacks exploit speculative execution to:
- Leak sensitive data: Read privileged memory via cache side-channels
- Bypass bounds checks: Access out-of-bounds memory speculatively
- Extract secrets: Exfiltrate encryption keys, passwords, etc.
High-risk code includes: - Code processing secrets (crypto, authentication) - Code with untrusted array indices - Kernel and hypervisor code
Resolution¶
Clang/LLVM Command Line¶
CMake¶
Meson¶
if meson.get_compiler('c').get_id() == 'clang'
add_project_arguments('-mspeculative-load-hardening', language: 'c')
endif
Selective Application¶
For performance reasons, apply to security-critical files only:
set_source_files_properties(
crypto.c auth.c secrets.c
PROPERTIES COMPILE_FLAGS "-mspeculative-load-hardening"
)
When to Suppress¶
This rule can be suppressed in the following scenarios:
- No secret processing: Code doesn't handle sensitive data
- Performance-critical code: SLH has significant overhead (10-50%)
- Non-x86 architecture: SLH is currently x86-specific
- GCC compiler: SLH is Clang/LLVM only
Performance Impact¶
Speculative Load Hardening has noticeable overhead:
| Workload Type | Typical Overhead |
|---|---|
| Compute-bound | 10-20% |
| Memory-bound | 20-50% |
| Cryptographic | 15-30% |
Consider applying selectively to security-critical code paths.
Caveats¶
- Only available with Clang/LLVM
- x86/x86_64 only (not ARM)
- Significant performance overhead
- Requires recompilation of all source files