concept · concepts/Control-Flow Integrity.md

Control-Flow Integrity

status: active · created 2026-06-20 · updated 2026-11-08 · 1 source · #security #software-security #exploitation #control-flow #memory-safety

A software-security property/technique that prevents attackers from hijacking a program's execution by enforcing that every control transfer follows a path of a control-flow graph (CFG) fixed ahead of time. Transfers the CFG doesn't sanction are blocked at runtime.

Grounded 2026-06-20 — captured as the human's own statement, then auto-grounded the same day by fetching and ingesting the canonical source (Control-Flow Integrity — Abadi et al., ACM TISSEC 2009 / CCS 2005). The capture confirmed: the human's definition matches the source exactly. Upgraded from #unsourced draft → active.

The idea

CFI stands for Control-Flow Integrity. The security policy is precise: software execution must follow a path of a Control-Flow Graph determined ahead of time (Control-Flow Integrity — Abadi et al.). The CFG can be derived by source-code analysis, binary analysis, or execution profiling; the original work used static binary analysis on Windows/x86. The order in which functions/instructions execute is constrained to legitimate, pre-computed paths.

Why it exists. Many exploits subvert machine-code execution, and "abnormal control-flow modification is an essential step in many exploits" regardless of the underlying flaw (Control-Flow Integrity — Abadi et al.). After defenses like stack canaries and non-executable data (NXD/DEP) were deployed, attackers pivoted to reusing existing code via corrupted indirect transfers — the class CFI targets. The paper demonstrates an exploit working even on Windows XP SP2 with hardware NXD plus a StackGuard analogue.

How it's enforced

CFI is implemented as an Inlined Reference Monitor via machine-code rewriting (Control-Flow Integrity — Abadi et al.):

  • Insert a bit-pattern ID at each legal destination of a computed/indirect transfer.
  • Insert an ID-check before each indirect call, jump, or return that verifies the destination's ID matches what the CFG allows; mismatches abort.

It holds even against an adversary with full control over all data memory — the IDs and ID-checks live in code, not data. The authors prove correctness for an abstract machine.

Three assumptions the guarantee rests on:

  • UNQ — Unique IDs: ID patterns appear nowhere in code but IDs/ID-checks.
  • NWC — Non-Writable Code: code can't be modified at runtime (else ID-checks get overwritten).
  • NXD — Non-Executable Data: data can't run as code (else attacker-supplied data carries the expected ID).

Cost. On SPEC benchmarks: average 16% slowdown (range 0–45%), ~8% binary-size growth — far cheaper than comparable techniques of the era (Control-Flow Integrity — Abadi et al.). CFI is also a foundation for a protected shadow call stack and software memory access control.

Later developments

The items below post-date the 2009 paper and are not from the ingested source — commonly-known background, candidates for a future source. The modern split is forward-edge CFI (indirect calls/jumps; e.g. LLVM CFI, Microsoft Control Flow Guard) vs. backward-edge CFI (returns, via shadow stacks). Hardware assists now ship in mainstream CPUs: Intel CET (shadow stack + indirect-branch tracking) and ARM PAC/BTI. #to-source.

Connections

  • Control-Flow Integrity — Abadi et al. — the canonical source grounding this page.

  • Match Process Weight to Stage and Stakes — see also (cross-domain): CFI is a concrete instance of that seed's ⚖️ "justified heaviness" quadrant — the kind of correctness/security rigor (here, ~16% runtime overhead) you adopt precisely when the stakes (exploitation risk) make the overhead worth it.

  • Allowlist over Blocklist — same security stance: CFI is default-deny for control flow — only the edges in the legitimate CFG are permitted, everything else is rejected. "Enumerate the legitimate, deny the rest" recurs from data handling (allowlisting sensitive fields) to control-flow security.

  • Provable Inference — sibling (2026-11-08): both enforce a specification fixed in advance (a CFG; a weight commitment) against an adversary who controls the runtime. CFI checks in-line for ~16%; provable inference proves after the fact for ~70–95× (Anthropic — Progress on Provable Inference for Large Language Models). The cost gap is the price of a check a third party can run without trusting the host.

This is the wiki's first software-security page. Future captures (ROP/JOP, DEP/W^X, shadow stacks, memory safety, Intel CET) should wire back here.

Sources

The wiki is the source. This door reads it at build time and never writes to it.