AD3033: RustEnableCET¶
Summary¶
| Property | Value |
|---|---|
| ID | AD3033 |
| Name | RustEnableCET |
| Category | Security |
| Severity | Warning |
| Applies to | ELF (Linux) - Rust x86_64 binaries |
Description¶
Rust binaries should be compiled with Intel Control-flow Enforcement Technology (CET) enabled. CET provides hardware-based protection against control-flow hijacking attacks like Return-Oriented Programming (ROP) and Jump-Oriented Programming (JOP).
How It Works¶
The rule checks Rust ELF binaries for:
- GNU property notes indicating CET features
- Indirect Branch Tracking (IBT) enabled
- Shadow Stack (SHSTK) enabled
CET consists of two components: - IBT (Indirect Branch Tracking): Validates indirect call/jump targets - SHSTK (Shadow Stack): Protects return addresses on a separate stack
Why This Matters¶
Rust's memory safety eliminates most buffer overflows, but control-flow hijacking can still occur through unsafe code, FFI, and compiler bugs. Intel CET provides hardware-enforced protection that complements Rust's compile-time safety.
Rust's Safety Gaps¶
Rust is memory-safe, but not invulnerable:
// Unsafe block - Rust's safety guarantees suspended
unsafe {
ptr::write(attacker_addr as *mut usize, malicious_value);
}
// FFI - C code may have vulnerabilities
extern "C" {
fn vulnerable_c_function(input: *const u8);
}
// These can enable control-flow hijacking
When CET Protects Rust Code¶
| Scenario | Rust Safety | CET Protection |
|---|---|---|
| Safe Rust | Full | Redundant but harmless |
| Unsafe blocks | None | Active protection |
| FFI to C/C++ | None | Active protection |
| Compiler bugs | May fail | Hardware catches |
| Memory corruption | If unsafe present | Blocks exploitation |
Defense-in-Depth Value¶
Without CET:
Bug in unsafe code β Memory corruption β ROP β Exploitation
With CET:
Bug in unsafe code β Memory corruption β ROP attempt
β CET fault β Safe crash
Real-World Rust Unsafe Usage¶
Many Rust crates use unsafe:
| Crate Category | Unsafe Usage | CET Value |
|---|---|---|
| std library | Yes (syscalls, ptr) | High |
| Crypto crates | Often (performance) | High |
| FFI bindings | Required | High |
| Embedded | Common | High |
| Pure safe Rust | None | Low (still harmless) |
CET Components for Rust¶
| Component | What It Protects |
|---|---|
| IBT | Indirect calls (vtables, fn ptrs) |
| Shadow Stack | Return addresses |
| Combined | Complete CFI coverage |
Deployment Considerations¶
Requirements:
- Rust nightly (for -Z flags)
- x86_64 target
- CET-capable CPU (Intel 11th gen+, AMD Zen 3+)
- CET-enabled OS (Linux 5.6+, Windows 10+)
Fallback:
- CET instructions as NOPs on older CPUs
- Binary runs, just without protection
Performance Considerations¶
Intel CET has minimal overhead due to hardware implementation:
| Component | Overhead |
|---|---|
| IBT (branch tracking) | <0.5% |
| Shadow Stack | <1% |
| Combined (full) | 1-2% |
Why overhead is minimal: - ENDBR64 instructions are essentially NOPs on the happy path - Shadow stack uses hardware registers and dedicated memory - No software validation neededβCPU handles it
Rust-specific considerations: - Safe Rust has minimal indirect calls (overhead is very low) - Unsafe blocks and FFI benefit most from CET - Overall Rust binary overhead typically <1%
Comparison:
| Platform | Protection | Overhead |
|---|---|---|
| Linux + CET | Hardware CFI | 1-2% |
| Windows + CFG | Software CFI | 1-2% |
| Clang CFI | Software type-CFI | 5-15% |
Despite Rust's memory safety, CET provides defense-in-depth:
- Unsafe code protection: Rust's
unsafeblocks can have vulnerabilities - FFI boundaries: C/C++ interop may introduce risks
- Compiler bugs: CET mitigates potential compiler vulnerabilities
- Hardware-level protection: Cannot be bypassed via software
Resolution¶
Rust Nightly Compiler¶
CET requires nightly Rust with unstable features:
Cargo Configuration¶
Add to .cargo/config.toml:
Build Script¶
Options¶
| Flag | Description |
|---|---|
-Z cf-protection=none |
Disable CET |
-Z cf-protection=branch |
Enable IBT only |
-Z cf-protection=return |
Enable Shadow Stack only |
-Z cf-protection=full |
Enable both IBT and Shadow Stack |
When to Suppress¶
This rule can be suppressed in the following scenarios:
- Stable Rust required: CET requires nightly compiler
- Non-x86_64 target: CET is Intel x86_64 only
- Older CPU target: Target CPUs without CET support
- Performance testing: When measuring baseline performance
Hardware Requirements¶
CET requires: - Intel Tiger Lake (11th Gen) or later, or - AMD Zen 3 or later - Linux kernel 5.6+ with CET support
Binaries with CET will run on older CPUs but without protection.
Caveats¶
- Requires Rust nightly compiler
- x86_64 Linux only
- Hardware support required for enforcement
- Some performance overhead for shadow stack