← New search

Other meanings of Control-flow integrity

Computer security

Control-flow integrity

Control-flow integrity (CFI) is a security defense mechanism that ensures a program's execution follows a predetermined control-flow graph, preventing attackers from hijacking control flow via memory corruption attacks such as buffer overflows or return-oriented programming (ROP).1

2005
Year introduced
First formalized by Abadi et al.
~25%
Overhead (typical)
Performance overhead for coarse-grained CFI
~5%
Overhead (fine-grained)
Performance overhead with advanced hardware support
1

Overview and mechanism

Control-flow integrity works by restricting indirect control-flow transfers (e.g., function pointers, return addresses, virtual calls) to a set of valid targets derived from a program's control-flow graph (CFG).1 The CFG is constructed statically or dynamically, and runtime checks ensure that every indirect jump lands on a legitimate target. This prevents common exploits like ROP, where attackers chain together short instruction sequences (gadgets) to execute arbitrary code. CFI can be implemented at various granularities: coarse-grained CFI groups targets loosely (e.g., all function addresses), while fine-grained CFI enforces per-indirect-call constraints, offering stronger security at higher performance cost.2 Hardware-assisted CFI, such as Intel's Control-flow Enforcement Technology (CET), incorporates shadow stacks and indirect branch tracking directly into the processor.3

2

History and development

The concept was first formally introduced by Martín Abadi, Mihai Budiu, Úlfar Erlingsson, and Jay Ligatti in 2005 at the ACM Conference on Computer and Communications Security.1 Their seminal paper proposed a static analysis to compute a CFG and then instrument binaries with runtime checks. Early implementations, such as WIT (Write Integrity Testing) and MoCFI, targeted x86 and ARM platforms, respectively. Over time, researchers developed more efficient variants: binCFI (2008) applied to binaries without source code, and CCFI (2014) focused on C++ virtual calls.4 Industry adoption began with Microsoft's Control Flow Guard (CFG) in Windows 8.1 (2013) and later with Clang's CFI support in LLVM (2015).5 Apples's iOS adopted CFI using ARM's pointer authentication in 2019.

3

Modern implementations and challenges

Today, CFI is deployed in major operating systems and compilers. Microsoft's Control Flow Guard uses coarse-grained CFI, while Clang's CFI provides fine-grained enforcement for C++ programs. Hardware support, such as Intel CET (available since 2020) and ARM Pointer Authentication (ARMv8.3), reduces performance overhead to under 5% for typical workloads.3 However, CFI is not a silver bullet. Forward-edge CFI can be bypassed by corrupting data that influences control-flow decisions (e.g., function pointer tables), and backward-edge CFI (return addresses) can be evaded via stack pivoting or overwriting shadow stacks. Advanced attacks like COOP (Counterfeit Object-oriented Programming) exploit the inherent flexibility in C++ virtual dispatch, requiring context-sensitive CFI.6

4

Lesser-known aspects

Beyond mainstream uses, CFI has niche applications. In embedded systems, MCFI (2016) provides protection for ARM Cortex-M microcontrollers, where memory and power constraints demand lightweight implementations.7 Another variant, CPI (Code Pointer Integrity), merges CFI with data pointer protection. A lesser-known historical thread: Erlingsson's earlier work on Program Shepherding (2003) at Cornell prefigured CFI by monitoring control flow in a kernel-level sandbox. In research, CFI has been extended to smart contracts (e.g., Ethereum bytecode CFI) and to enforce control-flow policies in WebAssembly (Wasm CFI). Also notable: the 2017 BOP (Block-Oriented Programming) attack demonstrates that even coarse-grained CFI can be bypassed if the attacker can reorder whole basic blocks, prompting the development of Fine-Grained CFI with context-sensitive labels.

Glossary

control-flow graph (CFG)
A representation of all possible execution paths in a program, used by CFI to determine valid targets.
return-oriented programming (ROP)
An exploit technique that chains short instruction sequences (gadgets) to hijack control flow.
shadow stack
A hardware-assisted mechanism that stores a separate copy of return addresses to detect corruption.
Coarse-grained CFI
CFI where all function addresses or all return targets are treated as valid, offering weaker security.
Fine-grained CFI
CFI that restricts each indirect call to a specific set of targets, providing stronger guarantees.

Control-flow integrity is an active research area; new bypass techniques and defenses appear regularly.