Skip to content

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:

  1. GNU property notes indicating CET features
  2. Indirect Branch Tracking (IBT) enabled
  3. 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 unsafe blocks 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:

RUSTFLAGS="-Z cf-protection=full" cargo +nightly build --release

Cargo Configuration

Add to .cargo/config.toml:

[build]
rustflags = ["-Z", "cf-protection=full"]

Build Script

#!/bin/bash
export RUSTFLAGS="-Z cf-protection=full"
cargo +nightly build --release

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

References