Fact-checked by Grok 2 weeks ago

Control-flow integrity

Control-flow integrity (CFI) is a mechanism that enforces a program's to adhere strictly to a predefined (CFG), thereby preventing attacks that attempt to hijack execution by redirecting control transfers to unauthorized locations. This technique mitigates a wide of exploits, such as overflows and code-reuse attacks like (ROP), by ensuring that indirect control transfers—such as jumps, calls, and returns—only target valid destinations as specified in the CFG. Introduced in 2005 by Martin Abadi and colleagues, CFI builds on earlier defenses like stack canaries and software fault isolation but provides a more comprehensive policy for aligning low-level machine-code behavior with high-level program intent. The core approach involves two phases: static analysis to compute a CFG representing all legitimate control transfers in the program, followed by binary instrumentation or compiler modifications to insert runtime checks that validate each transfer against the CFG, halting execution if a violation is detected. Early implementations, such as those for x86 Windows binaries, demonstrated an average performance overhead of about 16% on benchmarks like SPEC2000, while effectively blocking exploits in real-world malware like the Blaster and Slammer worms. Over the subsequent two decades, CFI has evolved from primarily software-based solutions to include hardware-assisted variants, addressing challenges like performance overhead and precision in CFG policies. Software implementations often focus on protecting code pointers and forward/backward edges through techniques like shadow stacks for returns and context-sensitive checks for indirect jumps, with notable advancements in modular CFI for separate compilation and fine-grained policies to counter advanced attacks like counterfeited control-flow (CFB). Hardware-based CFI, surveyed in over 20 architectures by 2017, leverages processor features such as Intel's Control-flow Enforcement Technology (CET)—which includes shadow stacks and endbranch instructions—and ARM's Pointer Authentication Codes (PACs) to enforce protections with lower runtime costs. By 2025, adoption remains uneven: approximately 28.7% of binaries in incorporate CFI for both forward- and backward-edge protection, up from 2.7% in Android 8.1, driven by priorities, while distributions like and show less than 1% prevalence due to implementation complexities and overhead concerns. Ongoing research continues to refine CFI for systems, environments, and integration with , emphasizing renewable policies to adapt to dynamic code changes.

Introduction

Definition and Purpose

Control-flow integrity (CFI) is a mechanism that ensures a program's adheres to a precomputed policy derived from its (CFG), thereby restricting indirect branches to only valid targets identified through static analysis. This enforcement prevents unauthorized alterations to the program's execution path by verifying that runtime control transfers match the static model at key points, such as indirect jumps and calls. The primary purpose of CFI is to mitigate control-flow hijacking attacks, where vulnerabilities like buffer overflows allow adversaries to redirect execution to unintended code. Introduced by Martin Abadi, Mihai Budiu, Úlfar Erlingsson, and Jay Ligatti in their seminal 2005 paper, CFI provides a robust defense by limiting the scope of exploits to predefined paths, offering stronger security guarantees compared to earlier techniques that address only specific vulnerability classes. CFI reduces the for code-reuse attacks by confining execution to legitimate sequences within the CFG, without requiring changes. It is particularly valuable for legacy software, as it can be retrofitted via binary rewriting to existing binaries. The original enforcement approach relies on software fault isolation, which inserts lightweight runtime checks to validate efficiently while maintaining performance.

Historical Context

Control-flow integrity (CFI) was first proposed in 2005 by researchers Martin Abadi, Mihai Budiu, Úlfar Erlingsson, and Jay Ligatti as a defense against control-flow hijacking attacks, such as buffer overflows and return-to-libc exploits. The seminal paper introduced CFI as a security property enforcing that program execution adheres to a precomputed , preventing deviations that could enable malicious behavior. An initial prototype was implemented using the compiler infrastructure, demonstrating feasibility for programs with acceptable overhead in controlled experiments; the work also included binary rewriting for x86 Windows binaries to support legacy software without source access. A revised version of the original work appeared in , providing deeper analysis of CFI principles, implementations, and applications, which solidified its theoretical foundations. Subsequent refined binary-level , exemplified by bin-CFI in 2013, which extended CFI to commercial off-the-shelf (COTS) binaries on x86/ without requiring source access or recompilation. In 2014, introduced Guard (CFG), a coarse-grained CFI variant, into to mitigate indirect call hijacking in user-mode applications. This was followed in 2016 by Intel's announcement of Control-flow Enforcement Technology (CET), a hardware extension offering shadow stacks and indirect branch tracking to support fine-grained CFI with minimal software overhead. Adoption of CFI gained momentum after high-profile vulnerabilities like Heartbleed in 2014, which exposed widespread memory corruption risks, and Spectre in 2018, which demonstrated speculative execution's potential for control-flow manipulation, spurring demand for robust hardware-assisted defenses. By 2023, CFI had been integrated into production environments, including Google's Chrome browser via the V8 JavaScript engine, where it enforces forward- and backward-edge checks to protect against exploitation in just-in-time compiled code. As of 2023, adoption remained uneven, with approximately 28.7% of binaries in Android 13 incorporating CFI for both forward- and backward-edge protection, compared to less than 1% prevalence in Linux distributions like Ubuntu and Debian due to implementation complexities and overhead concerns. Early software-only CFI implementations faced significant performance challenges, with runtime overheads averaging around 16% (up to 45%) on SPEC2000 benchmarks due to dynamic checks and code instrumentation, limiting deployment in performance-sensitive applications. These issues drove the evolution toward hybrid hardware-software approaches in the 2020s, leveraging features like Intel CET to offload enforcement and reduce overhead to under 5% in many cases.

Security Threats

Control-Flow Hijacking Attacks

Control-flow hijacking attacks exploit memory corruption vulnerabilities to alter a program's intended execution path by manipulating control data, such as return addresses on the or function pointers in memory. In a typical scenario, an attacker supplies excessive input that overflows a , overwriting adjacent control data and redirecting to malicious or unintended code locations upon the next , like a function return. This diversion allows the attacker to execute arbitrary instructions outside the program's legitimate . The impact of these attacks is severe, as they facilitate —directly executing attacker-supplied payloads—or the reuse of existing binary code snippets called gadgets to bypass protections and perform unauthorized operations, such as or . These exploits predominantly target software written in memory-unsafe languages like and , where bounds checking is absent, enabling unchecked writes to sensitive memory regions. issues, including those enabling control hijacking, account for approximately 50% of Microsoft-assigned CVEs as of 2025. Successful control-flow hijacking requires specific preconditions, including writable segments for both and , which allow of structures, and the presence of indirect transfers, such as virtual function calls or pointer-based jumps. While mitigations like Data Execution Prevention (DEP) prevent execution of injected and (ASLR) complicates address prediction, they fall short because they do not enforce validation of transfer destinations, leaving room for attacks like that repurpose legitimate . Recent analyses, such as those using the SeeCFI tool, highlight ongoing vulnerabilities in real-world binaries despite these defenses, underscoring the need for targeted validation.

Specific Exploit Techniques

Return-Oriented Programming (ROP) is a code-reuse attack technique where an attacker chains together short sequences of existing instructions, known as "gadgets," typically ending with a return instruction, to execute arbitrary malicious behavior without injecting new code. These gadgets are discovered in the program's binary or linked libraries, allowing the attacker to redirect control flow by overwriting the return address on the stack, effectively bypassing Data Execution Prevention (DEP) mechanisms that prevent execution of non-code memory regions by reusing legitimate, executable code segments. ROP was first formalized as a Turing-complete exploitation paradigm, demonstrating its ability to perform complex computations through gadget composition on architectures like x86. Jump-Oriented Programming (JOP) extends code-reuse attacks by focusing on indirect jumps rather than returns, mitigating limitations of ROP in environments where stack-based control is restricted or monitored. In JOP, attackers identify "jump gadgets"—instruction sequences concluding with an indirect jump—and link them via a centralized dispatch table constructed in attacker-controlled memory, enabling sequential execution of gadgets without relying on the return instruction or stack pivoting. This approach targets vulnerabilities exploitable through indirect control transfers, such as calls in object-oriented code, and has been shown to achieve on x86 systems by chaining gadgets from libraries like libc. Counterfeit Object-Oriented Programming (COOP) represents an advanced code-reuse technique tailored to C++ applications, exploiting virtual dispatch mechanisms to hijack without altering return addresses or direct jumps. In COOP, an attacker forges legitimate-looking objects in memory, corrupting virtual tables (vtables) to point to attacker-chosen methods, thereby inducing a chain of virtual function calls that execute desired operations while adhering to the program's type constraints and appearing benign to coarse-grained defenses. This method leverages object-oriented features like and polymorphism to bypass control-flow integrity checks that validate targets but not the contextual validity of calls, and it has been demonstrated to defeat multiple CFI implementations on real-world C++ binaries. A more recent variant, Coroutine Frame-Oriented Programming (CFOP), exploits vulnerabilities in C++20 coroutine implementations to bypass CFI protections in modern compilers. CFOP manipulates coroutine frames—data structures managing suspension and resumption—through heap corruption, allowing attackers to forge frames that redirect control flow to arbitrary gadgets while evading checks on indirect branches and object integrity. This technique succeeds across LLVM, GCC, and MSVC by abusing the lack of validation in frame allocation and resumption logic, enabling full code reuse even in hardened environments, as shown in exploits against 15 CFI schemes.

Fundamental Concepts

Direct and Indirect Control Transfers

In computer programs, control-flow transfers determine the sequence of instruction execution. Direct control transfers involve fixed, statically known destinations, such as unconditional jumps or calls to specific addresses embedded in the . These transfers are inherently safe from manipulation because their targets are resolved at and cannot be altered dynamically without modifying the executable itself. In contrast, indirect control transfers have destinations determined at through dynamic values, typically loaded from registers, locations, or pointers. Common examples include return instructions (ret), which fetch the target address from the ; virtual function calls in object-oriented languages, which resolve targets via virtual tables (vtables); indirect jumps or calls using computed addresses (e.g., jmp reg or call [reg]); switch statements implemented via jump tables, where the target is selected based on a computed index; and invocations of signal handlers, which often involve indirect calls through function pointers set by the program. These transfers are particularly susceptible to attacks that overwrite pointers or registers, as the target addresses are not fixed and can be corrupted through errors like buffer overflows. Control-flow integrity (CFI) policies address these vulnerabilities by deriving whitelists of valid targets specifically for each indirect transfer site. These policies are constructed through static analysis of the program's (CFG), which models all possible execution paths and identifies legitimate destinations reachable from each indirect site under normal conditions. For instance, for a return , the policy might limit targets to addresses of valid call sites in the CFG, while for a virtual call, it restricts targets to entries in the program's vtables. This approach ensures that only precomputed, safe targets are permitted, preventing deviations from the intended without requiring runtime computation of all possibilities.

Control-Flow Graphs and Policies

In control-flow integrity (CFI), the (CFG) serves as a foundational model representing the valid execution paths of a . It is a in which nodes correspond to basic blocks—sequences of instructions with a single and a single exit point—and edges denote permissible control transfers between these blocks. The CFG is typically constructed through static analysis of the program's binary or , identifying potential targets of branches, calls, and returns while conservatively approximating indirect transfers whose destinations are not immediately known at . The CFI policy defines the subset of CFG edges that must be respected during execution, particularly for indirect control transfers such as those via function pointers or returns, which are vulnerable to manipulation. This policy restricts forward edges, like indirect calls, to target only function entry points, and backward edges, like returns, to valid caller locations, thereby limiting the program's behavior to a precomputed safe subset of possible flows. Policies are derived from the full CFG but focus on enforcing constraints at indirect branch sites to prevent deviations that could enable attacks. CFI policies operate at varying levels of to balance and . Coarse-grained policies, often at the level, group multiple blocks under shared identifiers (e.g., one label per ), allowing transfers within broader classes but potentially permitting some invalid paths. Fine-grained policies, conversely, operate at the level, assigning unique identifiers to precise locations and enforcing stricter constraints on targets. Runtime checks validate adherence to the policy by verifying that each indirect transfer lands on an allowed destination. Formally, a CFI can be represented as a collection of allowed (source, ) pairs for each indirect control-transfer site in the program, where the source is the originating or , and the is a valid successor in the CFG. This set-theoretic view ensures that dynamic execution remains confined to the static , with proofs demonstrating that no unauthorized transfers are possible even under adversarial of . Such representations enable theoretical of and precision.

CFI Techniques

Coarse-Grained Approaches

Coarse-grained approaches to control-flow integrity (CFI) enforce broad policies that restrict indirect control transfers to large equivalence classes of potential targets, such as all functions compatible with a given pointer type, while minimizing overhead. These methods group valid targets loosely based on static analysis of program structure, allowing transfers only within these classes to approximate the intended (CFG) without enforcing precise per-target validation. Such policies prioritize practicality over strictness, making them feasible for real-world deployment where fine-grained checks would incur excessive costs. Key examples include type-based CFI, which validates targets by matching the runtime type of a against predefined equivalence classes derived from the program's , ensuring that indirect calls or jumps land only on functions with compatible signatures. Another variant involves blacklisting obviously invalid targets, such as non-function addresses, while permitting others within broad categories to reduce false positives. Early implementations, such as the 2005 Google prototype for Windows/x86 binaries, demonstrated these principles by inserting lightweight checks at indirect branches to enforce class-based restrictions computed from the program's CFG. Subsequent binary-level adaptations, like bin-CFI, extended this to commercial off-the-shelf (COTS) software by assigning a small set of labels (e.g., based on types and module locations) without requiring access. A notable example is CCFIR (Compact Control-Flow Integrity and Randomization), introduced in 2013, which applies policies to binaries by assigning distinct IDs for pointers and returns (e.g., a 3-ID scheme), redirecting indirect jumps to aligned stubs for validation, achieving low overheads around 4% on SPECint2000. These approaches offer significant advantages in and compatibility, with runtime overheads typically ranging from 5% to 10% on suites like SPEC CPU2000, enabling their application to legacy binaries without extensive recompilation. Their minimal —often just a few instructions per indirect transfer—preserves the original program's behavior while providing a defense against gross control hijacking. However, they remain susceptible to intra-class attacks, where an adversary redirects flow to a malicious within the same , such as a type-compatible gadget in chains. Additionally, their reliance on static analysis limits effectiveness against dynamic code loading or , as new targets may evade precomputed classes.

Fine-Grained Approaches

Fine-grained control-flow integrity (CFI) approaches enforce precise, context-sensitive policies that restrict indirect control transfers to exact, precomputed targets at each call site, using unique labels or identifiers assigned to functions and control-flow edges. This contrasts with coarser methods by minimizing valid targets per site through whole-program analysis, which constructs detailed control-flow graphs to derive whitelists of permissible destinations. Such policies enhance by preventing deviations even within the same function type, addressing limitations of broader classifications. Key techniques involve compile-time insertion of runtime checks, where branch targets are compared against site-specific whitelists before execution, often using bit-testing or cryptographic signatures for validation. Binary rewriting enables deployment on legacy code by inserting these checks and redirecting transfers to validation stubs, while label-based methods embed unique IDs at function entries for verification. These mechanisms require comprehensive static analysis to propagate labels across modules, ensuring compatibility with dynamic linking. Recent advancements include origin-sensitive CFI, which tracks pointer origins to further refine target sets, achieving overheads under 10% in some implementations as of 2019. Another approach leverages Pointer Authentication (), a hardware feature that embeds cryptographic modifiers in pointers to enforce fine-grained CFI; for instance, return addresses are signed with context-specific keys, verifying exact targets at each site. PAC-based systems achieve precision by tying authentication to call-site contexts, resisting pointer forgery in indirect transfers. These methods incur higher runtime overheads, around 20% on performance-sensitive benchmarks like SPEC CPU2006 due to frequent checks and analysis demands, but provide robust resistance to advanced attacks like Counterfeit Object-Oriented Programming (COOP) by enforcing per-site constraints that block object reuse chains. The need for whole-program analysis limits scalability in large, modular systems, though optimizations like signature-based validation can mitigate costs in kernels.

Auxiliary Mechanisms

Shadow stacks provide a mechanism to protect backward edges in control-flow transfers by maintaining a separate, protected dedicated exclusively to return addresses. Upon a function call, the return address is pushed onto both the regular data and the shadow ; on return, the address popped from the data is verified against the one from the shadow before proceeding. This ensures that (ROP) attacks, which rely on overwriting return addresses on the , are thwarted by preventing mismatched returns. The shadow is typically isolated in a protected region, such as a separate thread-local area or kernel-protected space, to prevent direct tampering. Vtable verification enhances control-flow integrity for object-oriented languages like C++ by safeguarding calls against corruption of virtual method tables (vtables). It involves computing and storing cryptographic hashes or identifiers for legitimate vtables at , then validating the vtable pointer's integrity before indirect calls through virtual functions. This check ensures that only authorized vtables are used, defending against attacks like counterfeit (COOP) that forge valid-looking objects to hijack virtual dispatch. Implementations often embed verification code at call sites, with minimal runtime checks using precomputed hashes to confirm vtable authenticity. For instance, techniques like VTint validate vtable integrity by hashing entries and comparing against expected values, incurring less than 2% performance overhead on benchmarks. Code-pointer integrity (CPI) extends CFI protections beyond control transfers to non-control pointers that , such as pointers embedded in structures. CPI enforces that all pointers remain unforgeable by selectively instrumenting accesses to validate pointer at load and store operations, using techniques like pointer or isolated . This prevents data-flow attacks where corrupted pointers could lead to , providing a formal guarantee of for code-referencing without full address-space protection. The approach instruments only necessary accesses, achieving practical overheads of 7%–21% on standard benchmarks like SPEC CPU2006. These auxiliary mechanisms are frequently integrated with core CFI policies to provide comprehensive protection, as standalone edge checks alone may leave gaps in backward edges or . For example, LLVM/Clang has supported shadow call stacks since version 7 (2018), allowing compilation with the -fsanitize=shadow-call-stack flag to combine them seamlessly with forward-edge CFI, resulting in isolated handling with typical overheads of 2%–5% for the stack component alone. Such combinations ensure robust defense against control-flow hijacking while maintaining compatibility with existing codebases.

Implementations

Compiler Support: LLVM/Clang

LLVM/Clang has provided integrated support for control-flow integrity (CFI) since LLVM version 3.4, following the implementation described in the seminal work on enforcing forward-edge CFI in production compilers. The primary mechanism for enabling fine-grained CFI in Clang is the -fsanitize=cfi flag, which instruments code to verify indirect control transfers against a compile-time control-flow policy derived via link-time optimization (LTO). This approach leverages LTO to analyze the entire program or module, generating efficient runtime checks such as jump tables for indirect calls, ensuring high precision without simplifying assumptions about the code. Key features of Clang's CFI implementation include support for shadow call stacks via the -fsanitize=shadow-call-stack flag, which protects return addresses by maintaining a separate for them, available on x86_64 and architectures. Vtable verification is handled through sub-flags like -fsanitize=cfi-vcall and -fsanitize=cfi-nvcall, which check virtual and non-virtual calls against expected dynamic types, preventing type-confused control hijacks in C++ code. Since (API level 28) in 2018, Clang's CFI has been enabled by default in security-critical components such as media frameworks, , and , using forward-edge protections to safeguard user-space and kernel code. Recent advancements include enhanced integration with Pointer Authentication Codes (PAC) starting from Clang versions supporting Armv8.3-A in 2023, where the -mbranch-protection flag enables hardware-accelerated signing of return addresses and pointers, complementing software CFI checks for backward-edge protection. Additionally, as of 2025, -compiled binaries can be analyzed for CFI presence using SeeCFI, a detection tool that identifies instrumentation patterns without source access, facilitating deployment verification. For optimal precision, Clang's CFI requires whole-program LTO via -flto, though ThinLTO (-flto=thin) offers a scalable with reduced compilation time while maintaining most benefits. Performance overhead is typically low, with runtime costs around 4% on benchmarks like SPEC CPU2006 when using LTO, and further mitigated to under 10% in practical workloads through optimizations like ThinLTO.

Compiler Support: GCC

The GNU Compiler Collection (GCC) introduced software-based control-flow integrity (CFI) support through the Virtual Table Verification (VTV) mechanism in version 4.9, released in April 2014, focusing on fine-grained forward-edge protection for C++ virtual function calls by verifying vtable pointers at runtime using type-based checks. This implementation instruments code to ensure that indirect calls via virtual functions adhere to the program's control-flow graph, with checks performed against a global table of verified vtables, providing protection against type-confused pointer dereferences without requiring link-time optimization (LTO) for basic operation. VTV builds upon coarser-grained defenses like Fortify Source, which mitigates buffer overflows that could indirectly enable control-flow hijacks, though it does not enforce full CFI policies on its own. Performance evaluations on SPEC CPU2006 benchmarks showed an average runtime overhead of 8% for VTV, with code size increases up to 15%, establishing its viability for production use while prioritizing precision for C++ workloads. Key features of GCC's CFI include type-based validation in VTV, which assigns unique identifiers to function types and checks compatibility during virtual dispatches to prevent cross-type attacks, covering over 99% of virtual calls in evaluated binaries. For backward-edge protection, GCC integrates with stack-smashing defenses via the -fstack-protector option, which inserts canaries to detect corruption, serving as a software to stacks in the absence of native support until hardware extensions were added later. Fine-grained CFI enforcement, particularly for forward edges, can leverage LTO (-flto) to compute more precise control-flow policies across compilation units, enhancing VTV's accuracy by propagating type information globally, though this increases compilation time by 20-50%. Hardware-assisted CFI, enabled via -fcf-protection, supports tracking (e.g., x86 ENDBR opcodes) and pointer authentication on compatible architectures, requiring LTO for full policy derivation and offering near-zero runtime overhead on supported hardware. Recent advancements in GCC's CFI support include expanded compatibility for architectures starting in version 15 (released in 2025), with implementation of the Zicfilp extension for forward-edge landing pads and Zicfiss for stateful shadow stacks, enabling efficient software-hardware hybrid CFI without dedicated registers. These improvements address 's lack of built-in CFI primitives, reducing overhead to under 2% on workloads through atomic stack operations like ssamoswap. However, GCC's CFI remains vulnerable to novel attacks like Coroutine Frame-Oriented Programming (CFOP), a code-reuse technique exploiting C++ frames to bypass protections in versions up to 14.2, as demonstrated in a 2025 analysis affecting major compilers including GCC. Overall adoption of GCC's CFI lags behind /, with only 12% of analyzed binaries in a 2025 study enabling software CFI compared to 28% for , attributed to GCC's emphasis on hardware reliance and less modular sanitizer integration. To enable CFI in , developers must use -fvtable-verify=std for VTV or -fcf-protection=full for hardware modes, both benefiting from -flto to enforce program-wide policies and minimize false positives in indirect transfers. Runtime overhead for hardware CFI is typically 1-3% on SPEC benchmarks, comparable to Clang's implementations, but GCC's less optimized integration results in higher mobile deployment costs, such as 5-10% battery impact on devices due to coarser LTO handling in toolchains.

Hardware Support: Intel CET

Intel's Control-flow Enforcement Technology (CET) is a hardware-based extension designed to protect against control-flow hijacking attacks, such as (ROP) and jump-oriented programming (JOP), by enforcing valid control transfers at the processor level. Introduced in 2019 with the Ice Lake microarchitecture (10th Generation processors), CET provides two primary mechanisms: shadow stacks for safeguarding return addresses and indirect branch tracking (IBT) for validating indirect control transfers. CET is enabled via the CR4.CET bit and requires verification of support through specific feature flags, such as CET_SS for shadow stacks and CET_IBT for indirect branch tracking. The shadow stack mechanism maintains a separate, protected stack solely for return addresses, managed by the Shadow Stack Pointer (SSP) stored in model-specific registers (MSRs) like IA32_PL3_SSP for user mode. During function calls, the processor automatically pushes the return address onto this shadow stack using instructions like CALL, while returns (RET or IRET) pop and compare it against the runtime stack; mismatches trigger a control-protection exception (#CP). IBT enforces that indirect branches (e.g., indirect JMP or CALL) land only on valid targets marked by endbranch instructions (ENDBR64 in 64-bit mode or ENDBR32 in 32-bit/compatibility mode), which reset a branch tracker in MSRs such as IA32_U_CET.TRACKER. Violations, including indirect branches to unmarked locations or invalid endbranch executions, also raise a #CP exception (interrupt vector 21) with an error code indicating the fault type, such as NEAR-RET for near returns. CET compatibility has been integrated into major operating systems starting in 2020, with version 20H1 (May 2020 Update) enabling user-mode shadow stack support for compatible , and 5.18 (May 2022) adding IBT for the , followed by user-space shadow stack support in 6.4 (June 2023). When properly implemented with compiler-generated endbranch markers and OS-managed MSRs, CET incurs minimal runtime overhead, typically less than 1% on standard benchmarks, due to its hardware-accelerated checks and NOP-like endbranch instructions. As an x86-specific extension, CET is limited to Intel processors supporting the feature (from Ice Lake onward) and requires explicit OS and compiler enablement, such as via parameters or Windows compatibility modes; it does not function on legacy x86 hardware without CET or on non-x86 architectures.

Hardware Support: ARM Pointer Authentication

ARM Pointer Authentication (PAC) is a hardware security extension introduced in the v8.3-A architecture in 2016, designed to protect pointers from unauthorized modification by embedding a cryptographic Pointer Authentication Code (PAC) into unused high-order bits of 64-bit pointers. The PAC is generated using a keyed cryptographic primitive based on the QARMA block cipher, leveraging one of five 128-bit secret keys stored in special system registers that are inaccessible to user-mode software. This mechanism enables probabilistic verification of pointer integrity, making it significantly harder for attackers to forge or corrupt pointers during control-flow hijacking attempts, thus serving as a foundational enabler for control-flow integrity (CFI) enforcement. The core mechanisms of PAC focus on authenticating critical control-flow transfers, particularly returns and calls. For return address protection, the PAC-IA instructions use the A-key for instruction addresses to sign the link register before pushing it onto the stack and verify it upon return using authentication instructions like AUTIASP. Similarly, PAC-IB employs the B-key to authenticate call targets, ensuring that indirect branches to function pointers are validated against expected signatures. In ARMv8.5 and later architectures, PAC integrates with shadow stack mechanisms, such as those using dedicated pointer-authenticated stacks, to provide stronger backward-edge CFI by separating return addresses from the main call stack and enforcing authentication on stack operations. Recent advancements have expanded PAC's adoption in production systems. Since 2023, Google's V8 JavaScript engine has incorporated PAC for CFI, signing return addresses and code pointers to mitigate in web applications running on devices. In 2025, introduced HyperGuard for Windows on ARM64, which leverages PAC to enhance kernel-mode protections against control-flow attacks by diversifying key usage and integrating with hypervisor-based integrity checks. PAC also resists attacks through address diversification, where the PAC computation incorporates pointer location and modifier values, preventing attackers from reliably forging signatures even with partial memory access or hardware faults. PAC is widely compatible with modern ARM hardware, including Apple's M-series processors, which implement it under the arm64e ABI for system-wide pointer signing in and macOS. Qualcomm's Snapdragon processors, starting with models like the 8cx Gen 3, support PAC for enhanced security in Windows and environments. Compiler support is mature, with providing pointer authentication intrinsics and ABI handling since 2019, alongside GCC's integration of PAC instructions from the same period. Typical performance overhead remains low at around 3% for return-address protection in instrumented applications, attributed to hardware-accelerated cryptography.

OS and Runtime Protections

Control Flow Guard (CFG) is a software-based control-flow integrity mechanism integrated into the Windows operating system, initially introduced in Windows 8.1 Update 3 in November 2014 to mitigate memory corruption vulnerabilities by validating indirect control transfers in user-mode applications. It employs a bitmap-based validation approach, where the operating system maintains a per-process bitmap protected by the kernel; this bitmap marks valid targets for indirect calls, such as function entry points, and the processor checks against it at runtime to prevent unauthorized jumps. For kernel-mode protection, Kernel Control Flow Guard (KCFG) extends this to the Windows kernel, leveraging Hypervisor-protected Code Integrity (HVCI) under Virtualization-Based Security (VBS); it became available starting with Windows 10 version 1703 (Creators Update) in April 2017, enhancing safeguards against control-flow hijacking in kernel code. Microsoft's eXtended Flow Guard (XFG), previewed in 2019 as an evolution of CFG, incorporates hash-based signatures to provide finer-grained validation of indirect calls by matching caller-callee prototypes, thereby addressing limitations in bitmap-only checks for external calls. Although prototyped and documented in tools like MSVC, XFG has not been fully released or enabled by in Windows as of 2025, remaining in experimental stages to balance security gains with performance overheads. In the , control-flow integrity support emerged around 2020 through compiler instrumentation, primarily via /Clang's CFI implementation, which enforces valid indirect branches and virtual calls at runtime to defend against code-reuse attacks. This integration allows kernel builds with CFI enabled using flags like -fsanitize=cfi, promoting adoption in distributions for improved exploit resistance without hardware dependencies. Browser runtimes have also adopted CFI enhancements; for instance, the V8 JavaScript engine in Chromium integrated Pointer Authentication Codes (PAC) for control-flow integrity in October 2023, signing return addresses and indirect branches on ARM64 architectures to prevent manipulation in JavaScript execution. This runtime protection complements OS-level checks by securing dynamic code paths in web applications. Android's runtime environment enforces CFI through LLVM/Clang, which became the default compiler in 2014, with CFI specifically enabled by default in Android Pie (2018) for key components like media frameworks, Bluetooth, and NFC to handle dynamic loading policies across shared libraries via cross-DSO CFI schemes that relax strict link-time target knowledge. This approach ensures integrity during library loading and execution, reducing vulnerabilities in modular apps without disabling the feature in production builds.

Limitations and Challenges

Bypass Methods

Control-flow integrity (CFI) protections, while effective against many control-flow attacks, have been circumvented through various software and hardware bypass techniques that exploit limitations or auxiliary vulnerabilities. These methods often imprecisions in the enforced (CFG), non-control data manipulations, or hardware-specific weaknesses, allowing attackers to redirect execution without violating core CFI checks. Research has demonstrated that such bypasses remain a significant challenge, particularly for coarse-grained CFI schemes that permit broad equivalence classes of valid targets. Software-based bypasses frequently target non-CFI gadgets or structural features in modern languages and compilers. Data-only attacks, for instance, manipulate program data structures to alter behavior without altering control flow, thereby evading CFI's focus on code pointers and indirect branches. These attacks corrupt sensitive data like function pointers in heaps or global offset tables, enabling unauthorized operations while respecting the program's CFG. A seminal example involves exploiting memory corruption to modify data-oriented state, such as kernel page tables, which CFI alone cannot prevent due to its lack of data integrity enforcement. More recent advancements include Coroutine Frame-Oriented Programming (CFOP), a 2025 code-reuse technique that hijacks C++ frames to bypass CFI in major compilers like , , and MSVC. CFOP exploits the fact that coroutine frames contain unchecked or weakly protected code pointers, allowing attackers to construct gadgets from coroutine suspension and resumption logic, even under fine-grained CFI policies. This method succeeds by chaining frame manipulations to redirect subtly, demonstrating vulnerabilities in how compilers handle asynchronous execution constructs. Hardware-assisted CFI implementations, such as Intel's Control-flow Enforcement Technology (CET) and ARM's Pointer Authentication Codes (), introduce additional bypass vectors through physical or speculative attacks. For , fault injection and side-channel techniques can leak authentication keys, enabling attackers to forge valid pointers. The attack, for example, uses to extract PACs from pointers, allowing reconstruction of authenticated control-flow targets and facilitating hijacking despite PAC's cryptographic signing. Similarly, CET's Indirect Branch Tracking (IBT) can be evaded via endbranch spoofing, where attackers forge ENDBRANCH instructions or use counterfeit objects to mimic valid targets. Techniques like Counterfeit Object-Oriented Programming () exploit type confusion to redirect IBT-protected calls to unauthorized gadgets, bypassing the requirement for legitimate ENDBRANCH markers at branch destinations. Mitigation gaps in CFI often stem from partial policies that overlook or enforce overly permissive CFGs, enabling classic es documented in early . Coarse-grained CFI, which groups targets by broad types or modules, suffers from CFG errors, allowing attacks like control-flow bending that warp indirect calls within equivalence classes to unintended locations. Between and , papers highlighted vulnerabilities such as loop-oriented programming (LOP), which chains loops as gadgets to both coarse CFI and stacks by avoiding direct s. Another example is the exploitation of attacks to manipulate addresses before CFI checks, undermining even 64-bit implementations. These gaps persist in s lacking comprehensive CFI, where non-control remains unprotected, amplifying the impact of memory errors. The evolution of CFI bypasses reflects ongoing adversarial adaptations, with coarse-grained schemes proving particularly vulnerable in real-world scenarios. Studies indicate that a substantial portion of memory corruption vulnerabilities, including those assigned CVEs in , can bypass coarse CFI due to its permissive policies, though exact figures vary by deployment. Fine-grained CFI and hardware mechanisms like reduce successful bypass rates significantly, often to under a quarter of coarse-grained cases, by tightening target validations and integrating cryptographic checks. However, hybrid attacks combining software gadgets with hardware leaks continue to challenge even advanced protections, underscoring the need for layered defenses.

Performance and Overhead

Control-flow integrity (CFI) mechanisms introduce performance overheads that vary based on implementation granularity, ranging from coarse-grained approaches with minimal impact to fine-grained ones with higher costs. Software-based CFI typically increases code size by 10-30%, as adds checks and for validating indirect branches and control transfers. For instance, modular CFI (MCFI) reports an average 17% code size increase across benchmarks, while fine-grained variants like FineIBT show 2-19% growth depending on the program. overheads on SPEC CPU benchmarks span 5-50%, influenced by check frequency and optimization level; the original CFI implementation averaged 16% slowdown (0-45% range), whereas optimized CFI achieves about 1% on SPEC CPU 2006. Coarse-grained CFI tends toward the lower end (e.g., 0.78% for slot-based forward-edge enforcement), while fine-grained policies can reach 8-10% or more, such as 8.54% for binary-level CFI or 7.6% for origin-sensitive CFI. Several factors modulate these overheads. Link-time optimization (LTO) enhances CFI precision but extends compile times significantly, as it enables whole-program analysis for better indirect call resolution. Hardware-assisted CFI substantially reduces costs: Intel Control-flow Enforcement Technology (CET) with Indirect Branch Tracking (IBT) limits runtime impact to 1-7% in fine-grained setups, while Pointer Authentication Codes () yield under 0.5% average overhead for pointer integrity checks and as low as 2.5% in contexts. On mobile devices, these hardware features minimize battery drain compared to software-only approaches, though frequent PAC signing can still add minor energy costs in pointer-heavy workloads. Recent analyses of deployed binaries highlight practical measurements. Tools like SeeCFI, introduced in 2025 to detect CFI adoption, underscore that real-world slowdowns average around 15% in instrumented applications, aligning with historical benchmarks but varying by deployment scale. Optimizations such as (PGO) mitigate this by informing devirtualization and inlining, reducing forward-edge CFI overheads in GCC and LLVM implementations through runtime profile data. Trade-offs in CFI design balance security and efficiency: coarse-grained variants suit legacy systems with low overhead (e.g., <5% runtime) but weaker protection, while fine-grained enforcement for critical applications offers robust integrity at higher costs (10-30% combined), prioritizing security in high-value targets like servers or embedded systems.

References

  1. [1]
    [PDF] Control-Flow Integrity Principles, Implementations, and Applications
    The en- forcement of a basic safety property, Control-Flow Integrity (CFI), can prevent such attacks from arbitrarily controlling program behavior.
  2. [2]
    [PDF] A survey of Hardware-based Control Flow Integrity (CFI) - arXiv
    Control Flow Integrity (CFI) is a term used for computer security techniques which prevent CRAs by monitoring a program's flow of execution (control flow). CFI ...Missing: primary | Show results with:primary<|control11|><|separator|>
  3. [3]
    Modular control-flow integrity - ACM Digital Library
    We present Modular Control-Flow Integrity (MCFI), a new CFI technique that supports separate compilation. MCFI allows modules to be independently instrumented ...
  4. [4]
    Twenty Years Later: Evaluating the Adoption of Control Flow Integrity
    Apr 28, 2025 · In this article, we introduce SeeCFI, a tool to detect the presence of a memory corruption mitigation technique called Control Flow Integrity (CFI).Missing: primary | Show results with:primary
  5. [5]
    Renewable Just-In-Time Control-Flow Integrity - ACM Digital Library
    Oct 16, 2023 · Control-flow Integrity Principles, Implementations, and Applications. ACM Transactions on Information and System Security (TISSEC) 13, 1 ...
  6. [6]
    Control-flow integrity | Proceedings of the 12th ACM conference on ...
    The enforcement of a basic safety property, Control-Flow Integrity (CFI), can prevent such attacks from arbitrarily controlling program behavior.
  7. [7]
    Control-flow integrity principles, implementations, and applications
    The enforcement of a basic safety property, control-flow integrity (CFI), can prevent such attacks from arbitrarily controlling program behavior.
  8. [8]
    [PDF] Control Flow Integrity for COTS Binaries - USENIX
    This paper is included in the Proceedings of the. 22nd USENIX Security Symposium. August 14–16, 2013 • Washington, D.C., USA. ISBN 978-1-931971-03-4.<|separator|>
  9. [9]
    Control Flow Guard for platform security - Win32 apps | Microsoft Learn
    Dec 17, 2024 · Control Flow Guard (CFG) is a highly-optimized platform security feature that was created to combat memory corruption vulnerabilities.Missing: 2014 | Show results with:2014
  10. [10]
    On the Effectiveness of Intel's CET Against Code Reuse Attacks
    Jun 12, 2016 · Intel's recent announcement of their hardware support for a form of Control Flow Integrity (CFI) has raised a lot of interest among the ...
  11. [11]
    Control-flow Integrity in V8 - V8.dev
    Oct 9, 2023 · Control-flow integrity (CFI) is a security feature aiming to prevent exploits from hijacking control-flow.Forward-Edge Cfi · Jit Memory Integrity · EvaluationMissing: history timeline milestones<|control11|><|separator|>
  12. [12]
    [PDF] Control-Flow Integrity: Precision, Security, and Performance
    For each mechanism, we evaluate (i) protected types of control-flow transfers, (ii) the precision of the protection for forward and backward edges. For open- ...
  13. [13]
    [PDF] Hardware-based Control-Flow Integrity: An Overview
    Control-Flow Integrity (CFI) has emerged as a promising technique for mitigating Control-. Flow Hijacking (CFH) attacks. Over the past two decades, ...
  14. [14]
    [PDF] Control Hijacking Attacks
    Developing buffer overflow attacks: ▫ Locate buffer overflow within an ... ▫ At function prologue, copy return address RET and SFP to “safe” location ...
  15. [15]
    [PDF] Exploits - Buffer Overflows and Format String Attacks
    Control Flow Hijack: Always Computation + Control computation. + control shellcode (aka payload) padding. &buf. 15. • code injection. • return-to-libc. • Heap ...
  16. [16]
    [PDF] Lecture 2: Control Flow Integrity - Cornell: Computer Science
    Feb 3, 2017 · Control Flow Integrity is a general approach to mitigating all control flow hijacking attacks, including both return-to-libc attacks and return- ...
  17. [17]
    A proactive approach to more secure code - Microsoft
    Jul 16, 2019 · Figure 1: ~70% of the vulnerabilities Microsoft assigns a CVE each year continue to be memory safety issues. So many tools, so little time.
  18. [18]
    Exploit protection reference - Microsoft Defender for Endpoint
    Mar 25, 2025 · Control flow guard (CFG)​​ For example, an attacker might use a buffer overflow vulnerability to overwrite memory containing a function pointer, ...
  19. [19]
    [PDF] Return-Oriented Programming: Systems, Languages, and Applications
    In this paper, we present a new form of attack, dubbed return-oriented programming, that categorically evades W+X protections. Attacks using our technique ...
  20. [20]
    [PDF] Jump-Oriented Programming: A New Class of Code-Reuse Attack
    In this paper, we present an alternative attack paradigm called jump-oriented programming (JOP). ... First, while we have found that JOP is capable of arbitrary ...
  21. [21]
    [PDF] Evading Control Flow Integrity by Hijacking C++ Coroutines - USENIX
    Aug 15, 2025 · Abstract. Code reuse attacks exploit legitimate code sequences in a binary to execute malicious actions without introducing new code.
  22. [22]
    [PDF] Control-Flow Integrity - Columbia CS
    This paper describes and studies one mitigation technique, the enforcement of Control-Flow Integrity (CFI), that aims to meet these standards for ...
  23. [23]
    [PDF] Out Of Control: Overcoming Control-Flow Integrity
    In this paper, we examine the security implications of such looser notions of CFI: are they still able to prevent code reuse attacks, and if not, how hard is it.Missing: milestones | Show results with:milestones
  24. [24]
    [PDF] Control-Flow Integrity: Precision, Security, and Performance - arXiv
    Jan 27, 2017 · Most CFI mechanisms determine the set of valid targets for each indirect control-flow transfer by computing the CFG of the program. The security ...
  25. [25]
    [PDF] A Theory of Secure Control Flow
    Abstract. Control-Flow Integrity (CFI) means that the execution of a program dynamically follows only certain paths, in accordance with a static policy.
  26. [26]
    [PDF] On the Ineffectiveness of Coarse-Grained Control-Flow Integrity ...
    Aug 20, 2014 · ROP attacks re- quire no code injection, and have already been shown to be powerful enough to bypass fine-grained memory randomization (ASLR) ...
  27. [27]
    On the Effectiveness of Type-based Control Flow Integrity - arXiv
    Oct 24, 2018 · On the Effectiveness of Type-based Control Flow Integrity. Authors:Reza Mirzazade Farkhani, Saman Jafari, Sajjad Arshad, William Robertson, ...
  28. [28]
    [PDF] Fine-Grained Control-Flow Integrity for Kernel Software
    Control-flow integrity (CFI) aims to restrict the execution of a program to its control-flow graph (CFG). However, there are several challenges in en- forcing ...
  29. [29]
    Control-Flow Bending: On the Effectiveness of Control-Flow Integrity
    While recent research has shown that coarse-grained CFI does not stop attacks, fine-grained CFI is believed to be secure. We argue that assessing the ...
  30. [30]
    [PDF] Practical Control Flow Integrity and Randomization for Binary ...
    Based on these approaches, CCFIR can stop control-flow hijacking attacks including ROP and return- into-libc. Results show that ROP gadgets are all eliminated.
  31. [31]
    Fine-Grained Control-Flow Integrity Through Binary Hardening
    Control-Flow Integrity CFI is a promising security property that restricts indirect control-flow transfers to a static set of well-known locations. We present ...
  32. [32]
    [PDF] PAC it up: Towards Pointer Integrity using ARM Pointer Authentication
    Control-flow attacks exploit memory errors to hijack pro- gram execution by overwriting code pointers (function return addresses or function pointers).
  33. [33]
    [PDF] Thwarting Control-Flow Attacks with ARM Pointer Authentication
    Apr 30, 2021 · FIPAC is an efficient solution to provide protection against software- and fault-based CFI attacks on basic block level on modern ARM devices.
  34. [34]
    [PDF] Fine-Grained Control-Flow Integrity through Binary Hardening
    Control-Flow Integrity (CFI) is a promising security property that restricts indirect control-flow transfers to a static set of well-known locations. We present ...Missing: milestones | Show results with:milestones
  35. [35]
    [PDF] Counterfeit Object-oriented Programming
    Oct 24, 2015 · We also discuss how COOP can reliably be prevented by precise C++-aware CFI, defenses that provide (spatial and temporal) integrity for C++ ...
  36. [36]
    [1811.03165] Shining Light On Shadow Stacks - arXiv
    Nov 7, 2018 · We present a comprehensive analysis of all possible shadow stack mechanisms along three axes: performance, compatibility, and security.Missing: seminal | Show results with:seminal
  37. [37]
    [PDF] Enforcing Forward-Edge Control-Flow Integrity in GCC & LLVM
    Aug 20, 2014 · The main contributions of this paper are: • We present the first CFI implementations that are fully integrated into production compilers without.
  38. [38]
    [PDF] Code-Pointer Integrity - USENIX
    Oct 6, 2014 · This paper introduces code-pointer integrity (CPI), a way to enforce precise, deterministic memory safety for all code pointers in a program. ...
  39. [39]
    ShadowCallStack — Clang 22.0.0git documentation - LLVM
    ShadowCallStack protects programs against return address overwrites by saving return addresses to a separate 'shadow call stack' and loading them in the epilog.
  40. [40]
    [PDF] The Performance Cost of Shadow Stacks and Stack Canaries
    Hard- ware shadow stack schemes are usually extremely fast, in- strument all RETs (even unintended RETs), and do not require recompilation, but introduce ...<|control11|><|separator|>
  41. [41]
    Control Flow Integrity — Clang 22.0.0git documentation - LLVM
    Clang includes an implementation of a number of control flow integrity (CFI) schemes, which are designed to abort the program upon detecting certain forms of ...Missing: prototype | Show results with:prototype
  42. [42]
    Pointer Authentication — Clang 22.0.0git documentation
    PAuth (sometimes referred to as PAC, for Pointer Authentication Codes) is an AArch64 architecture extension that provides hardware support for pointer ...
  43. [43]
    Improving control-flow integrity for Linux on RISC-V - LWN.net
    Jun 13, 2024 · RISC-V improves CFI using Zicfilp for forward flow, Zicfiss with a shadow stack for backward flow, and ssamoswap for atomic stack swaps.Missing: improvements | Show results with:improvements
  44. [44]
    Instrumentation Options (Using the GNU Compiler Collection (GCC))
    This option enables floating-point type to integer conversion checking. We check that the result of the conversion does not overflow. Unlike other similar ...
  45. [45]
    Fighting exploits with Control-Flow Integrity (CFI) in Clang - Red Hat
    May 26, 2020 · In this post, we look at Control-Flow Integrity (CFI) protection implemented by the Clang compiler for x86_64 architecture.<|control11|><|separator|>
  46. [46]
    A Technical Look at Intel® Control-Flow Enforcement Technology
    Jun 13, 2020 · Intel Control-Flow Enforcement Technology (Intel CET) enables the operating system to create a shadow stack, which is designed to be protected from application ...Missing: 2016 | Show results with:2016
  47. [47]
    Intel® Control-flow Enforcement Technology - 010 - ID:655258
    12th Generation Intel® Core™ Processors. Datasheet, Volume 1 of 2. Download as PDF. View More. ID, Date, Version, Classification. 655258, 06/15/2023.
  48. [48]
    [PDF] Control-flow Enforcement Technology Specification - kib.kiev.ua
    Control-flow Enforcement Technology (CET) provides the following capabilities to defend against ROP/JOP ... instructions or of CET-defined changes to existing ...
  49. [49]
    Control-flow Enforcement Technology (CET) Shadow Stack
    Control-flow Enforcement Technology (CET) covers several related x86 processor features that provide protection against control flow hijacking attacks. CET can ...
  50. [50]
    R.I.P ROP: CET Internals in Windows 20H1
    Jan 5, 2020 · As a reminder, Intel CET is a hardware-based mitigation that addresses the two types of control-flow integrity violations commonly used by ...
  51. [51]
    Intel CET Indirect Branch Tracking Submitted For Linux 5.18 - Phoronix
    Mar 26, 2022 · Intel has been working on both Shadow Stack and Indirect Branch Tracking support for the Linux kernel. With this pull IBT is ready to go for ...
  52. [52]
    Intel CET Shadow Stack Support Set To Be Introduced With Linux 6.4
    Mar 21, 2023 · After being in development for years, Intel's shadow stack support is set to be merged for the upcoming Linux 6.4 cycle.
  53. [53]
    [PDF] Pointer Authentication on ARMv8.3 - Qualcomm
    fine-grained Control-Flow-Integrity [6] where each indirect call-site can only call a subset of functions based on a compile-time generated control-flow graph.
  54. [54]
    Arm CPU Security Update: Pointer Authentication - Arm Developer
    Aug 21, 2025 · The Pointer Authentication feature was implemented in Arm Architecture version Armv8.3-A (FEAT_PAuth). Later versions of the Arm Architecture ...
  55. [55]
  56. [56]
    Exploit Development: Unveiling Windows ARM64 Pointer ...
    On ARM64 installations of Windows, an ARM64-specific HyperGuard extent exists – the PAC system register extent. This extent is used by HyperGuard to ask the ...
  57. [57]
    Preparing your app to work with pointer authentication
    Overview. The arm64e architecture introduces pointer authentication codes (PACs) to detect and guard against unexpected changes to pointers in memory.
  58. [58]
    [PDF] KPAC: Efficient Emulation of the ARM Pointer
    by Qualcomm's Snapdragon 8cx Gen 3 SoC [16], which 163 brings the PA also ... [22] “Apple pointer authentication guidelines.” 2023. [Online]. Available ...
  59. [59]
    Pointer Authentication | Secure Systems Group
    PACStack. A popular run-time attack technique is to compromise the control-flow integrity of a program by modifying function return addresses on the stack.
  60. [60]
    [PDF] BYPASS CONTROL FLOW GUARD COMPREHENSIVELY - Black Hat
    Control Flow Guard (CFG) is a mitigation that prevents redirecting control flow to unexpected location. It was first introduced in Windows 8.1 Preview, but ...
  61. [61]
    The Current State of Exploit Development, Part 1 - CrowdStrike
    Aug 6, 2020 · With a nod to efficiency for users, indirect calls that are protected by CFG are validated using a bitmap, with a set of bits indicating if a ...
  62. [62]
    [PDF] How KCFG and KCET Redefine Control Flow Integrity in the ...
    Aug 3, 2025 · All indirect call targets which are known at compile-time are stored in a read-only, kernel- protected (and per-process) “CFG bitmap”.
  63. [63]
    How the MSVC Compiler Generates XFG Function Prototype Hashes
    Nov 12, 2020 · Microsoft is currently working on Xtended Flow Guard (XFG), an evolved version of Control Flow Guard (CFG), their own control flow integrity<|control11|><|separator|>
  64. [64]
    eXtended Flow Guard Under The Microscope | Offensive Security
    May 18, 2021 · The aim of this blog post is to cast more light on whether XFG is truly a more secure and hardened version of Control Flow Guard (CFG).
  65. [65]
    Control-flow integrity for the kernel - LWN.net
    Jan 22, 2020 · Control-flow integrity (CFI) is a technique used to reduce the ability to redirect the execution of a program's code in attacker-specified ways.
  66. [66]
    Queue the Hardening Enhancements - Android Developers Blog
    May 9, 2019 · LLVM's Control Flow Integrity (CFI) was enabled in the media frameworks, Bluetooth, and NFC in Android Pie. CFI makes code reuse attacks ...
  67. [67]
    Control flow integrity | Android Open Source Project
    Oct 9, 2025 · Control flow integrity (CFI) is a security mechanism that disallows changes to the original control flow graph of a compiled binary.Examples and source · Implementing system CFI · Troubleshooting
  68. [68]
    [PDF] SoK: On the Effectiveness of Control-Flow Integrity in Practice
    Aug 13, 2024 · On the effectiveness of type-based control flow integrity. In Proceedings of the 34th An- nual Computer Security Applications Conference ...
  69. [69]
    [PDF] Exploitation Techniques and Defenses for Data-Oriented Attacks
    Abstract—Data-oriented attacks manipulate non-control data to alter a program's benign behavior without violating its control- flow integrity.
  70. [70]
    [PDF] Attacking ARM Pointer Authentication with Speculative Execution
    We provide an end-to-end example to show how to use the PAC-. MAN attack to bypass Pointer Authentication and assist a control- flow hijacking attack. For ...
  71. [71]
    [PDF] Bypassing Intel CET with Counterfeit Objects (COOP) - Squarespace
    Intel CET. ○ The original Intel specs included two HW-based mitigations: ▫ Shadow Stack. ▫ Indirect Branch Tracking (IBT) - not yet implemented. ○ Our ...
  72. [72]
    [PDF] Control-Flow Bending: On the Effectiveness of Control-Flow Integrity
    Aug 12, 2015 · Control-Flow Integrity (CFI) is a defense which pre- vents control-flow hijacking attacks. While recent re- search has shown that coarse ...Missing: milestones | Show results with:milestones
  73. [73]
    Loop-Oriented Programming: A New Code Reuse Attack to Bypass ...
    In this paper, we propose a new code reuse attack, named loop-oriented programming (LOP), aiming to bypass both coarse-grained CFI and shadow stack.
  74. [74]
    On the Effectiveness of Control-Flow Integrity under Stack Attacks
    Control-flow integrity: Principles, implementations, and applications. In ACM SIGSAC Conference on Computer and Communications Security, CCS, 2005. Digital ...