Skip to content

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:

  1. DWARF debug info with -mspeculative-load-hardening flag
  2. 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

clang -mspeculative-load-hardening -o myapp myapp.c

CMake

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    add_compile_options(-mspeculative-load-hardening)
endif()

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

References