Janus: Compiler-Based Defense Against Transient Execution Attacks Using ARM Hardware Primitives Ciyan Ouyang, Peinan Li*, Yubiao Huang, Dan Meng, and Rui Hou State Key Laboratory of Cyberspace Security Defense Institute of Information Engineering, CAS, Beijing, China
arXiv:2605.10049v1 [cs.CR] 11 May 2026
Abstract We present Janus, a compiler-based security framework that mitigates transient execution attacks like Spectre and control-flow hijacking on ARM64 platforms. Janus integrates speculative execution and control flow dependencies with PA modifiers, using PA and BTI microarchitectural features to prevent control-flow speculation attacks and secure both control flow and speculative execution through existing control-flow integrity mechanisms. To optimize performance, Janus minimizes overhead by merging defense operations across different defense layers (modifier fusion) and reusing registers of protected variables (carrier reuse), while maintaining strong security guarantees. Evaluation on SPEC CPU2017 shows an average performance overhead of 3.85%, with real-world applications exhibiting overheads ranging from 2.97% to 7.80%. Janus offers effective speculative execution security and low performance and code size overhead, making it a robust solution for ARM-based systems.
Keywords transient execution attacks, ARM Pointer Authentication, compiler hardening ACM Reference Format: Ciyan Ouyang, Peinan Li*, Yubiao Huang, Dan Meng, and Rui Hou. 2026. Janus: Compiler-Based Defense Against Transient Execution Attacks Using ARM Hardware Primitives. In 63rd ACM/IEEE Design Automation Conference (DAC ’26), July 26–29, 2026, Long Beach, CA, USA. ACM, New York, NY, USA, 7 pages. https://doi.org/10.1145/3770743.3804170
1
Introduction
Speculative execution in modern processors has led to Spectre attacks[18], which exploit microarchitectural side channels to leak isolated data, threatening system confidentiality. While several mitigations have been proposed, none fully balance security, performance, and deployability. Hardware-level solutions, such as modifying processor components or designing new instructions, have long deployment cycles and limited adaptability, offering inadequate protection for existing hardware and emerging threats. Industry and consumers urgently require defense solutions that can be quickly deployed on current hardware. * Corresponding author: Peinan Li ([email protected])
This work is licensed under a Creative Commons Attribution 4.0 International License. DAC ’26, Long Beach, CA, USA © 2026 Copyright held by the owner/author(s). ACM ISBN 979-8-4007-2254-7/2026/07 https://doi.org/10.1145/3770743.3804170
Prevailing software defenses fall into two categories: full speculation barriers, like lfence[16], which offer security but cause significant performance degradation, and partial mitigations, like SLH[6], which reduce attack surfaces by identifying leakage gadgets. However, pattern-matching approaches struggle to cover diverse attack gadgets and often lose effectiveness with complex control-flow semantics. Existing software defenses fail to address the security issues of speculative execution. Complete speculation barriers incur high costs, while gadget-based[32] defenses can’t guarantee long-term security. A deployable defense on current hardware should: (1) abort illicit speculation without affecting legitimate speculation, (2) verify speculation trustworthiness at its source, and (3) constrain speculation targets to limit attackers’ ability to create malicious speculation chains. Fortunately, existing hardware primitives[8], such as Arm’s Branch Target Identification (BTI) and Pointer Authentication (PA)[20], can be repurposed to achieve these goals through their microarchitectural side effects, a concept we validate experimentally in section 4. BTI’s property of squashing invalid speculative jumps enforces characteristic 3 by restricting all speculative indirect branches to valid BTI-guarded targets. The key to characteristics 1 and 2 lies in PA’s microarchitectural side effect: a failed verification during speculation squashes the pipeline instead of raising an architectural fault. Janus operationalizes this by using a csel instruction to conditionally poison a PA modifier based on the true branch outcome. On a mis-speculated path, the poisoned PA modifier guarantees the verification will fail, thereby triggering a targeted speculation squash at the point of divergence and eliminating the need for gadget identification. Janus’s defense uses BTI to create a zero-overhead, coarse-grained security baseline for indirect branches, covering both architectural and microarchitectural states. This prevents jumps to illicit gadgets and allows PA to focus on fine-grained, cryptographically backed control-flow binding and speculative state verification, ensuring comprehensive security with minimal PA instruction overhead. In summary, the contributions are fourfold: • Unified Framework for Control-Flow Speculation Defense: We introduce the first framework leveraging memory safety hardware to provide Control-Flow Integrity (CFI)[4] and control data integrity at both architectural and microarchitectural levels, defending against Spectre attacks V1[18], V2[1], V5[19]) and mitigating CFI threats like ROP/JOP and DOP. • Signature Neutralization for Metadata Protection: We propose a "signature neutralization" mechanism that uses csel to dynamically encode speculative state and metadata,
Memory safety prevents programs from accessing incorrect memory locations, avoiding vulnerabilities like buffer overflows[10] and use-after-free errors[23]. These flaws can lead to data corruption, information leakage, control-flow hijacking[3, 27, 29] or no-control data attacks[5]. Control-flow hijacking attacks manipulate the execution flow of programs, while no-control data attacks target the data integrity of applications; CFI and Data flow integrity DFI[7] are security techniques designed to prevent these types of vulnerabilities. Modern CPUs enforce security through hardware mechanisms. Janus builds on Arm PA for fine-grained pointer integrity using a PAC. The hardware verifies this signature before pointer use, invalidating it if verification fails. Arm BTI provides coarse-grained control-flow protection, ensuring indirect branches target only legal locations. Similar primitives exist on x64 and RISC-V, making Janus cross-platform compatible.
2.3
Threat Model
We assume the platform enforces a Write Xor Execute (W⊕X)[25, 28] policy, preventing code injection attacks, and that no other memory safety or Spectre defenses are in place. The attacker aims to compromise the confidentiality of critical secrets and exploit
4
Verifying the Microarchitectural Foundations of Janus
The design of Janus is predicated on the principle that modern hardware security features possess undocumented or under-utilized microarchitectural side-effects that can be repurposed to defend against transient execution attacks. While official ARM documentation and academic works like the PACMAN allude to these behaviors [20, 26], their reliability and specific mechanisms have not been deeply investigated for defensive use. This chapter provides the first empirical validation of two such critical properties on the ARMv8-A architecture, which form the foundation of our defense. MISPREDICTION Delay ACCESS PREDICTION ACCESS Transient Execution
USE USE
TRANSMIT TRANSMIT
Committed
MISPREDICTION
ACCESS
USE
MISPREDICTION
ACCESS
USE Delay TRANSMIT
MISPREDICTION
ACCESS Delay
USE
TRANSMIT
USE
TRANSMIT
MISPREDICTION Delay ACCESS
TRANSMIT
switchpoline No SLH defense
Memory Safety and Hardware Protection Primitives
Traditional memory safety mechanisms weren’t designed for Transient Execution Attacks (TEAs)[11, 33], leaving metadata used by defenses like ASLR[24] and stack canaries[30] vulnerable. Attacks like PACMAN show how transient execution can compromise memory safety hardware, such as brute-forcing pointer authentication. Additionally, hardware-based defenses like FineIBT lack explicit protection against speculative execution. As shown in fig. 1, TEA defenses typically operate at the backend of the attack pipeline, providing weaker security and failing to optimize synergistically with architectural memory safety. Janus combines architectural and microarchitectural security primitives, leveraging their side effects with intelligent compiler instrumentation. We chose the ARM platform for its mature ecosystem, but note that Janus’s core design is portable to x86 and RISC-V (similar hardware primitives[14, 17] exist or are coming soon). The loss of CFI is a critical threat to memory safety and aligns closely with defending against transient execution attacks. Janus focuses on enforcing CFI, validating speculative control flow at the processor’s branch decision stage. This approach ensures synergistic protection at both architectural and microarchitectural levels.
Janus
2.2
Motivation and Design Goals
ConTExT
Spectre attacks manipulate processor predictions to access isolated data and leak it through microarchitectural side channels. Spectre attacks fall into two categories: control-flow Spectre (e.g., V1, V2, V5) exploiting branch prediction errors, and data-flow Spectre (e.g., V4) exploiting memory dependency mispredictions. A more dangerous hybrid threat, Speculative Memory-error Abuse (SMA)[9], combines speculative execution with memory corruption. These attacks exploit speculative execution’s ability to suppress fatal exceptions, leaking secret metadata used by defenses like cryptographic Pointer Authentication Code(PAC)[26] and ASLR[13]. Once these defenses are compromised, attackers can escalate to more reliable architectural attacks, forming a dangerous attack cycle. Existing software mitigations are ineffective against these advanced hybrid threats.
3
lfence
2 Background 2.1 Spectre Attacks
vulnerabilities in memory safety and control-flow Spectre gadgets. The attacker has the following capabilities: • An arbitrary write primitive to corrupt code pointers or control-flow data. • The ability to influence the speculative outcomes of conditional branches and the targets of indirect branches in the victim program. • The ability to monitor CPU microarchitectural state via a side channel, enabling the exfiltration of transiently accessed data. The attacker and victim may execute on the same physical machine. We consider attacks that manipulate data-flow speculation to be orthogonal to the defenses provided by Janus.
Worse Performance,Better Security
invalidating signatures on mis-speculated paths to prevent leakage. • Optimized Synergistic Defense Implementation: We optimize memory safety and speculative execution defense by reusing existing BTI and PA instructions, reducing instrumentation and refining the set of variables requiring protection. By analyzing variables shared by both attack classes, we further refine and minimize the set of variables needing protection. • Comprehensive Evaluation on ARMv9 Hardware: We evaluate Janus on ARMv9 hardware, showing performance overhead below 5% on SPEC CPU 2017, successful compilation of real-world applications like Nginx, and verified security using Spectre proof-of-concept (PoC) exploits and the publicly available PACMAN exploit.
Figure 1: Janus in the Hierarchy of Transient Execution Defenses
target program LLVM frontend Application .c/.cpp
Intermediate Representation (IR)
apply
Janus defense framework LLVM AAResults
LLVM backend opt
IR pass
AliasAnalysisPASS GetDOPVarsPASS
LLVM LoopAnalysis
GetBranchInfoPASS
External CFI analyzer
GetBranchTargetPASS
LLVM DT/PDT
External DFI analyzer External gadget analyzer
Machine Intermediate Representation
llc
.ll/.bc
AnalysisBTITargetPass
apply
.so
IRsaveInfo (Global data)
.so
MIR pass
transform InstruIRmetadata transform AnalysisPATargetPass
Executable
.mir
InstruBTIMIR
transform IRbridgeMIR Janus-dryrun
register
InstruPAMIR register
json
AlignBranch
Janus
register
DependencyAnalysisPass GetSpectreVarsPASS CountSettlementPointPass
Figure 2: The architecture of the Janus compiler framework, detailing the pipeline of analysis, transformation, and instrumentation passes. A. The BTI enforcement targets indirect branches with BTI inListing 1: The Speculation-Squashing Effect of PA. structions, ensuring speculative execution only targets legitimate 1 void test_pa_speculation_squash ( bool condition ){ locations and preventing control-flow hijacking, such as ROP/JOP. 2 // Trigger misprediction on `if `. 3 MISTRAIN_BRANCH_PREDICTOR ( condition ); B. The PA Fine-Grained CFI uses Arm PA to assign a unique 4 if ( condition ) { 5 // Barrier : PAC validation fails here . modifier to each function pointer, verifying that indirect branch 6 VERIFY_PAC ( CORRUPTED_POINTER ); targets transfer control flow to the intended destination. 7 // Transmitter : Reached only if barrier fails . 8 MEM_SIDECHANNEL_ACCESS ( secret_A ); C. The PA Data Integrity signs critical DOP variables, ensuring 9 } the validity of data sources used for branch decisions and mitigating 10 } DOP attacks. D. The Ordered PA Authentication mechanism enforces a strict Listing 2: The Speculative Redirection Deterrence of BTI. sequence, ensuring that PA instructions precede DOP variable veri1 void NON_BTI_TARGET () { // Barrier : the absence of a BTI . fication. This prevents attackers from reading the PA signature that 2 // Transmitter : Reached only if barrier fails . 3 MEM_SIDECHANNEL_ACCESS ( secret_B ); follows, thwarting PACMAN attacks. 4 } 5 E. The Conditional PA Modifier mechanism encodes the true 6 void test_bti_speculation_deterrence ( void (* fptr ) () ){ outcome of conditional branches into a PA modifier. If the branch 7 // Mistrain BTB to point to the invalid target . 8 MISTRAIN_BTB_TO (& NON_BTI_TARGET ); mispredicts, the PA verification fails and aborts speculative execu9 // speculatively call NON_BTI_TARGET . tion, defending against Spectre V1 attacks. 10 fptr () ; 11 } Through the synergistic interaction of these mechanisms, Janus establishes a comprehensive and efficient framework for defending First, we investigate Arm PA, which architecturally faults on a against speculative execution attacks. PAC mismatch. We hypothesize that a PAC validation failure occurs early enough in the pipeline to prevent mis-speculated instructions 5.2 Janus Analysis and Instrumentation from executing and leaking data(listing 1). Second, we examine Arm Pipeline BTI, which prevents control flow from landing at illegal targets. Janus implements the core defense mechanisms as a multi-pass We hypothesize that a BTB mistrain to a non-BTI location will be LLVM compiler framework, as shown in fig. 2. The pipeline starts at detected, stalling or squashing the speculative pipeline(listing 2). the IR level, where analysis passes identify control-flow structures. To test these hypotheses, we conducted microbenchmark tests The GetBranchTarget and GetBranchInfo passes handle CFI and on the Radxa Orion O6 platform, used in the evaluation in secDOP analysis, respectively. CFI analysis identifies indirect branch tion 7. This platform features FEAT_FPAC and FEAT_FPACC_SPEC call sites and their potential targets, creating an equivalence class for [21], which are critical for pointer authentication and speculative each site, while DOP analysis flags conditional branches influenced execution control. FEAT_FPAC allows the processor to verify pointer by external inputs as requiring protection. authenticity via cryptographic signatures, while FEAT_FPACC_SPEC The Janus defense framework is independent of these analyensures speculative control flow integrity. Using performance counsis techniques and focuses on efficient enforcement, allowing the ters and a timing-based side channel, we confirmed that PAC valida-
5 Janus: Design and Implementation 5.1 Core Mechanisms Janus defends against three key vulnerabilities: CFI hijacking, DataOriented Programming (DOP)[15], and speculative execution attacks. fig. 3 illustrates how the five core mechanisms of Janus (A–E) address these threats.
B:PA Fine-Grained CFI
A:BTI Enforcement
ROP,JOP,COOP illegal targets irrelevant targets
A
B
intended targets D:Ordered PA authentication
Indirect Branch site
tion failure and BTI target mismatches prevent transient execution of gadgets. Specifically, we observed that the cache did not read erroneous branch data during mis-speculation, confirming that speculative execution was squashed before gadgets could execute.
Spectre V2/V5 A B
illegal targets irrelevant targets intended targets
E: Conditional PA Modifier
Spectre V1 True target False target PACMAN
True target Conditional D, E Branch site
C
False target DOP
C:PA Data Integrity
Figure 3: Janus Defense Mechanisms
Vulnerable Code Snippet int initialize_uid(int flag,int input) { .bb2
// ...... int uid = input; return uid;
.bb7 .bb1 .bb3 .bb4 .bb5 .bb6 .bb8
} void (*handlers[])(void) = {hadmin,h1,h2,h3}; /*omit definition of hadmin,h1,h2,h3*/ void root_request(int input, int idx,int hidx) { //...... int uid = initialize_uid(input); // DOP vulnerability if (uid == 0) { // admin path unsigned char secret = pdata[idx]; varray[secret * 4096] = 0;//spectre v1 } else { // user path ...} // ...... handlers[hidx](); // indirect call }
.bb2:initialize_uid mov ret
.bb1:root_request ...... bl initialize_uid
w0, w1
.bb4:admin_path .bb3:root_request cmp w0, #0 b.ne user_path
ldrb w2, [pdata, x1] lsl x2, x2, #12 strb wzr, [varray, x2] b .L_continue
true false
.bb5:user_path //....user path code ....
.bb6:root_request ldr blr
.bb7:h_admin //....admin handler ....
x4, [handlers, x3, lsl #3] x4 .L_continue .bb8:root_request // ... (function epilogue) ... ret
.bb2:initialize_uid mov w0, w1 pacda x0, x10 ret .bb3:root_request autda x0,x10 true cmp w0, #0 mov x11, #0xd5f csel x11, x11, xzr, eq pacda x0, x11 b.ne user_path false .bb5:user_path //....user path code .... .bb7:h_admin bti c cmp x11, #0x9c2 csel x11 x11, xzr, eq authda x0, x11
.bb1:root_request ...... bl initialize_uid .bb4:admin_path autda x0, x11 ldrb w2, [x_pdata, x19] % ...spectre gadget... b .L_continue .bb6:root_request ldr x4, [handlers, x3, lsl #3] mov x11, #0x9c2 pacda x0,x11 blr x4 .L_continue .bb8:root_request // ... (function epilogue) ... autia x30, x12 ret
Figure 4: Vulnerable C Code Snip- Figure 5: CFG of Unprotected Assembly Figure 6: CFG of Janus-Hardened Assembly pet. Code. Code. *Janus’s Instrumentation for Unified Architectural and Microarchitectural Defense. Instrumentation for architectural Control Integrity is highlighted in mitigations for Spectre attacks in , and dual-purpose instructions providing unified protection in .
replacement of current analysis with more precise static or dynamic methods, such as multi-layer type analysis (MLTA) for CFI or inter-procedural taint analysis for DFI. The AnalysisBTITarget and AnalysisPATarget passes use mappings from internal or external analyses to generate PA modifiers for injection and verification. Janus’s policy-agnostic design ensures consistent PA-based operations, supporting various CFI/DFI policies without altering the core enforcement code. The metadata required for instrumentation is passed securely to the MachineIR level through a custom global structure, IRsaveInfo, simplifying inter-pass communication. Finally, passes like InstruBTIMIR and InstruPAMIR inject BTI and PA instructions into Machine Basic Blocks (MBBs), ensuring both precision and efficiency in the final code generation.
5.3 From Vulnerability to Hardening: The Janus Workflow fig. 4 illustrates a C code snippet with a DOP vulnerability, Spectre V1 vulnerability, and an indirect call vulnerability, its unprotected Control-Flow Graph (CFG)(fig. 5), and the hardened assembly fragments after Janus protection (fig. 6). These figures will help clarify how Janus: • Applies existing CFI/DFI analysis results. • Extends CFI/DFI defenses to protect against control-flow Spectre attacks. 5.3.1 Applying CFI/DFI Analysis to Establish Architectural Defenses. As a policy-agnostic enforcement platform, Janus can translate external static or dynamic security policies into hardware-enforced protections for both CFI and DFI. For DFI, Janus uses the “Source-to-Sink” model. It reads external taint analysis policies and applies the taint tag IDs as PA modifiers. Instrumentation is performed at the specified “source” (definition points) and “sink” (use points). For example, as shown in basic blocks .bb2 and .bb3, Janus inserts a pacda instruction to sign the data at its generation point and an autda to verify it at its use point, ensuring data-flow integrity. For CFI, Janus employs a hybrid scheme. Unlike traditional hardware CFI, which verifies directly at the call site, Janus avoids tracking the PAC lifecycle. Compared to software CFI schemes, Janus cryptographically hardens the checkpoint, addressing microarchitectural weaknesses. As shown in basic block .bb6, Janus inserts a
,
lightweight mov x11, #0x9c2 and pacda x0, x11 at the indirect call site to encode the control-flow intent. At the callee entry (.bb7), a BTI instruction ensures verification. The cmp and csel instructions compare the incoming tag, and if the comparison fails, csel clears x11, causing the subsequent authda x0, x11 verification to fail, trapping control-flow hijacking. 5.3.2 Extending Foundational Defenses to Mitigate Spectre Attacks. Janus reuses its architectural control-flow integrity mechanisms to defend against speculative execution attacks targeting control flow. For conditional branch mispredictions (Spectre V1), Janus uses the PA mechanism from its DFI protection. As shown in .bb3, the csel and pacia instructions dynamically encode the branch’s true outcome into the PA modifier (x11). During misprediction, the speculative path carries an incorrect modifier, causing the autia verification in .bb4 to fail and squashing the pipeline, preventing Spectre gadgets from leaking data. This approach also defends against side-channel attacks like PACMAN, as any attempt to leak a PAC on a mis-speculated path is thwarted by the premature aut* verification failure. For indirect branch mispredictions (Spectre V2), Janus introduces a “cryptographic assertion at entry” mechanism. As shown in .bb7, the cmp and csel sequence at the function entry creates a speculation barrier. If a Spectre-V2 attack mispredicts the entry, the incorrect context causes the comparison cmp x11, #0x9c2 to fail, and csel selects an invalid sentinel value (e.g., xzr). The following authda verification fails, squashing speculation before any potentially dangerous code executes. This mechanism also protects against Spectre V5 attacks caused by RSB mispredictions. A mispredicted return that jumps to .bb7 triggers the same verification failure, preventing execution.
5.4
Cross-Domain Security Policy Fusion and Performance Optimization
The core advantage of Janus lies in its comprehensive security coverage and synergistic optimization framework. It fuses policies from different analyses (CFI, DFI, Spectre) and reuses hardware-level instructions, providing robust protection with minimal overhead. Janus employs two key optimization mechanisms to reduce overhead: Modifier Fusion (MF): Traditional defense approaches insert isolated protection instructions for different threats (e.g., data-flow
Algorithm 1: Multi-Threat PA Modifier Fusion Input: 𝑆 𝐷𝐹 𝐼 , 𝑆𝑆𝑝𝑒𝑐𝑡𝑟𝑒 : Sets of policies as (𝑣, 𝑙𝑜𝑐, 𝑚𝑜𝑑 ) tuples. Output: 𝐼𝑂𝑝𝑡𝑖𝑚𝑖𝑧𝑒𝑑 : Optimized set of instrumentation instructions. Initialize 𝑃𝑜𝑙𝑖𝑐𝑦𝑀𝑎𝑝 ← ∅ ; Initialize 𝐼𝑂𝑝𝑡𝑖𝑚𝑖𝑧𝑒𝑑 ← ∅ ; 3 foreach policy (𝑣, 𝑙𝑜𝑐, 𝑚𝑜𝑑 ) in 𝑆 𝐷𝐹 𝐼 ∪ 𝑆𝑆𝑝𝑒𝑐𝑡𝑟𝑒 do 4 𝑃𝑜𝑙𝑖𝑐𝑦𝑀𝑎𝑝 [ (𝑣, 𝑙𝑜𝑐 ) ] ← 𝑃𝑜𝑙𝑖𝑐𝑦𝑀𝑎𝑝 [ (𝑣, 𝑙𝑜𝑐 ) ] ∪ { policy } ;
1 2
foreach key (𝑣, 𝑙𝑜𝑐 ) in 𝑃𝑜𝑙𝑖𝑐𝑦𝑀𝑎𝑝.keys ( ) do 𝑝𝑜𝑙𝑖𝑐𝑖𝑒𝑠 ← 𝑃𝑜𝑙𝑖𝑐𝑦𝑀𝑎𝑝 [ (𝑣, 𝑙𝑜𝑐 ) ] ; 7 𝑚𝑜𝑑𝐷𝐹 𝐼 ← get_modifier_or_default (𝑝𝑜𝑙𝑖𝑐𝑖𝑒𝑠, DFI, 0) ; 8 𝑚𝑜𝑑𝑆𝑝𝑒𝑐𝑡𝑟𝑒 ← get_modifier_or_default (𝑝𝑜𝑙𝑖𝑐𝑖𝑒𝑠, Spectre, 0) ; 9 𝑚𝑜𝑑 𝐹𝑢𝑠𝑒𝑑 ← 𝑚𝑜𝑑𝐷𝐹 𝐼 ⊕ 𝑚𝑜𝑑𝑆𝑝𝑒𝑐𝑡𝑟𝑒 ; 10 𝑖𝑛𝑠𝑡𝑟 ← GeneratePA (𝑣, 𝑙𝑜𝑐, 𝑚𝑜𝑑 𝐹𝑢𝑠𝑒𝑑 ) ; 11 𝐼𝑂𝑝𝑡𝑖𝑚𝑖𝑧𝑒𝑑 .add (𝑖𝑛𝑠𝑡𝑟 ) ; 5
6
12
Optimization (LTO), function inlining, and loop-aware optimizations to eliminate redundant pointer re-signing in safe loop bodies.
6
return 𝐼𝑂𝑝𝑡𝑖𝑚𝑖𝑧𝑒𝑑 ;
Carrier Reuse (CR): Unlike traditional CFI schemes, Janus reduces overhead by reusing existing registers for CFI verification. Instead of allocating a new register, it searches for an existing variable (e.g., DFI-protected) to carry the CFI context. As shown in algorithm 2, Janus "piggybacks" the CFI verification onto the existing PA verification, merging DFI and CFI checks into a single operation with zero additional register overhead. If no suitable carrier is found, it checks if a stack-related register, such as LR, can be used; otherwise, it falls back to a general-purpose register like the non-volatile register x10. Algorithm 2: Fusing CFI Context into Existing PA Policies
Implementation
We implemented a Janus prototype as out-of-tree passes for the LLVM compiler (v20.1.0). The framework has three parts: Basic CFI and Naive DOP-sensitive variable detection: Implements simple type-based CFI and basic DOP-sensitive variable detection, including branch variables and taint analysis for a single call level. Janus supports more complex CFI/DFI schemes, but for prototyping transient execution defenses, we kept the CFI/DFI strength simple. This part comprises 3,700 C++ SLOC. External analysis results reader: A 600-line program that reads external analysis results. Instrumentation: Inserts necessary instructions at the MachineIR level. Instrumentation occurs after optimization but before register allocation, ensuring security gadgets remain unaffected by later optimizations and preserving PA modifier register availability. The out-of-tree design enhances portability, and a binary validator checks the disassembled machine code against IR-level metadata to confirm protection correctness. Performance overhead (%)
hijacking and side-channel attacks), leading to redundant performance costs. For example, a variable protected by both DFI and Spectre policies triggers two separate PA signing operations. To address this, Janus uses a Cross-Domain Policy Fusion mechanism, identifying variables requiring dual protection, combining their PA modifiers (mod_DFI and mod_Spectre) using XOR, and instrumenting a single PA instruction with the fused modifier (algorithm 1). This reduces instruction overhead, minimizes tag collisions, and simplifies policy management.
18 16 14 12 10 8 6 4 2 0
no CR/no MF CR/no MF
_s
ch
en
rlb
e 0.p 60
s s s s s s s z_ k_ p_ 4_ g_ la_ cf_ tp 26 7.x ee jen bm 5.m ne 65 ps 1.l nc 5.x 60 ee 64 62 .om .xala d 0 . 1 3 62 63 62
_s
cc
2.g 60
MF/no CR CR/MF
Figure 7: SPEC CPU 2017 performance results.
7 Evaluation 7.1 Experimental Setup
We use a unified strategy for performance and security evaluation on the Radxa Orion O6 development board with 16 GB of DDR5 memory, featuring an ARM Cortex-A720 CPU with 4 big cores at 2.8 GHz, 4 medium cores at 2.4 GHz, and 4 little cores at 1.8 GHz, 2 foreach (𝑐𝑎𝑙𝑙 _𝑠𝑖𝑡𝑒, 𝑐 𝑓 𝑖 _𝑡𝑎𝑔) in 𝑆𝐶𝐹 𝐼 do running Ubuntu 24 (Kernel 6.11) with LLVM/Clang 20.1 (+LTO, 3 𝑡𝑎𝑔_𝑟𝑒𝑔 ← GetTagPassingRegister ( ) ; -O3). For consistency, we fixed the CPU to the 4 big A720 cores at 2.8 4 𝑐𝑎𝑟𝑟𝑖𝑒𝑟, 𝑜𝑟𝑖𝑔_𝑚𝑜𝑑 ← FindCarrier (𝑐𝑎𝑙𝑙 _𝑠𝑖𝑡𝑒, 𝑃𝐸𝑥𝑖𝑠𝑡𝑖𝑛𝑔 ) ; GHz. The platform provides direct hardware access for running PoC 5 𝑐𝑎𝑙𝑙𝑒𝑒 ← GetCalleeFrom (𝑐𝑎𝑙𝑙 _𝑠𝑖𝑡𝑒 ) ; exploits and measuring microarchitectural phenomena via perfor6 𝑚𝑜𝑑 _𝑟𝑒𝑔 ← AllocateScratch ( ) ; 7 𝐼 𝐹 𝑖𝑛𝑎𝑙 .add ( CreateInst ( "MOV", 𝑡𝑎𝑔_𝑟𝑒𝑔, 𝑐 𝑓 𝑖 _𝑡𝑎𝑔), at caller epilogue ) ; mance counters, eliminating thermal throttling and virtualizationinduced jitter, ensuring accurate SPEC CPU 2017 benchmarking 8 𝐼 𝐹 𝑖𝑛𝑎𝑙 .add ( CreateInst ( "CMP", 𝑡𝑎𝑔_𝑟𝑒𝑔, 𝑐 𝑓 𝑖 _𝑡𝑎𝑔), at callee ) ; and security validation. Experiments were conducted in a mini9 if 𝑐𝑎𝑟𝑟𝑖𝑒𝑟 is not null then 10 𝐼 𝐹 𝑖𝑛𝑎𝑙 .add ( CreateInst ( "CSEL", 𝑚𝑜𝑑 _𝑟𝑒𝑔, 𝑜𝑟𝑖𝑔_𝑚𝑜𝑑, XZR, EQ ), at callee ) ; mal, single-user Linux environment with CPU frequencies locked to maximum and benchmark processes pinned to dedicated cores 11 𝐼 𝐹 𝑖𝑛𝑎𝑙 .add ( CreateInst ( "AUTHDA", 𝑐𝑎𝑟𝑟𝑖𝑒𝑟, 𝑚𝑜𝑑 _𝑟𝑒𝑔), at callee ) ; using taskset. Input: 𝑆𝐶𝐹 𝐼 : Indirect call sites as (𝑐𝑎𝑙𝑙 _𝑠𝑖𝑡𝑒, 𝑐 𝑓 𝑖 _𝑡𝑎𝑔) tuples. 𝑃𝐸𝑥𝑖𝑠𝑡𝑖𝑛𝑔 : Existing PA policies as (𝑣𝑎𝑟𝑖𝑎𝑏𝑙𝑒, 𝑙𝑜𝑐, 𝑚𝑜𝑑 ) tuples. Output: 𝐼 𝐹 𝑖𝑛𝑎𝑙 : Final set of instrumentation instructions. 1 Initialize 𝐼 𝐹 𝑖𝑛𝑎𝑙 ← ∅ ;
12 13
else if IsNonLeaf(callee) then 𝐼 𝐹 𝑖𝑛𝑎𝑙 .add ( CreateInst ( "CSEL", 𝑚𝑜𝑑 _𝑟𝑒𝑔, SP, XZR, EQ ), at callee ) ;
14
𝐼 𝐹 𝑖𝑛𝑎𝑙 .add ( CreateInst ( "AUTHIA", LR, 𝑚𝑜𝑑 _𝑟𝑒𝑔), at callee epilogue ) ;
15
𝐼 𝐹 𝑖𝑛𝑎𝑙 .add ( CreateInst ( "CMP", 𝑡𝑎𝑔_𝑟𝑒𝑔, GetTagOf (𝑐𝑎𝑙𝑙𝑒𝑒 ) ), at callee entry ) ;
16
return 𝐼 𝐹 𝑖𝑛𝑎𝑙 ;
Finally, Janus optimizes performance through both compilerlevel and instruction-level techniques, including LLVM’s Link-Time
7.2
Performance Evaluation
7.2.1 SPEC CPU 2017. We evaluate Janus’s runtime overhead using the SPEC CPU 2017 benchmark suite, specifically the SPEC speed Integer suite, which includes nine C/C++ applications. Using the uninstrumented build as the baseline, we compare performance with modifier fusion (MF), carrier reuse (CR), and all optimizations (including LTO) enabled, as shown in Figure 7. We report the geometric mean of overhead across five runs. The unoptimized version has an overhead of 8.17%. With MF, it drops to
5.74%; with CR, it further drops to 5.27%; and with all optimizations, it reduces to 3.85%. In most tests, MF provides greater performance improvement, while CR has a more significant effect in tests like 605 and 657, likely due to higher register pressure where CR’s register optimization is more beneficial. The above represents the overall overhead of the framework. Additionally, we measured the net overhead specifically for instructions used in speculative execution defense. By subtracting the overhead of strip-janus (which replaces and removes Spectre-related protection instructions such as csel) from the overhead of full-janus, the average overhead for the SPEC CPU 2017 test is 0.58%. 7.2.2 Real-World Applications. We evaluated the performance overhead on two real-world applications: Nginx (I/O-intensive) and SQLite (CPU/memory-intensive). Nginx: We benchmarked Nginx using the HTTP tool wrk, generating HTTP requests for one minute with 4 threads and 128 concurrent connections. The test was run three times, serving 1KB, 100KB, and 1MB files, with 4, 4, and 2 worker threads to maximize CPU utilization. The throughput degradation ranged from 0.13% to 2.97%. SQLite: We stress-tested SQLite using its Speedtest benchmark, which executes database operations and reports total execution time. The test used an in-memory database to isolate CPU overhead, with default settings and compiler annotations to avoid unnecessary instrumentation. With the added protection, the average completion time for SQLite increased by 7.80%. Table 1: Asymmetrical ablation study of Janus overhead on SQLite and Nginx. Benchmark Config.
Perf. Ov. (%)
w/o opts w/ CR only w/ MF only Full
SQLite
9.58 9.15 8.27 7.80 1k 100k
w/o opts 0.95 w/ CR only 0.83 w/ MF only 0.32 Full 0.13
Nginx
Code Size Ov. (%) 16.57 9.86 8.24 8.32
1m
3.85 1.34 3.61 1.07 3.23 0.82 2.97 0.48
19.84 16.61 15.14 13.42
Code size increase (%)
7.2.3 Code Size Increase Evaluation. We measured Janus’s impact on binary code size for the SPEC CPU 2017 benchmarks and two real-world applications. As shown in Figure 8, the code size overhead for Janus ranges from 8.32% to 13.42% for the real-world applications and 2.8% to 20.2% for the SPEC CPU 2017 benchmarks. no CR/no MF CR/no MF
35 30 25 20 15 10 5 0
er 0.p
60
s s _s _s _s _s _s _s z_ cf_ cc pp 64 ng ela mk 7.x et 2.g sje .le cb .x2 5.m 65 mn ep 41 25 60 lan o e 6 6 . a d 0 1. 3.x 62 63 62
s
h_
nc
lbe
MF/no CR CR/MF
60
Figure 8: Code-size increase for Janus.
7.3
Security Evaluation
CFI and DFI: Janus defends against Spectre attacks by leveraging external CFI/DFI analysis results and using basic non-control
data protection (conditional variables) for testing. It passed all ConFIRM tests except JIT and effectively protected against string buffer attacks on conditional branch variables. Traditional Spectre Attacks: To evaluate Janus’s effectiveness against transient execution attacks, we implemented PoC attacks for Spectre V1, V2, and V5 on the ARM platform, using the Radxa Orion O6 development board. The baseline PoC attacks successfully leaked secrets via a cache side channel. After applying Janus, all attacks were mitigated, with no secrets recovered, and cache probes resulted in misses, confirming speculative execution paths were squashed before accessing sensitive data. The key advantage of Janus’s defense is its insensitivity to diverse leakage gadget patterns. Unlike defenses that rely on gadget identification, Janus focuses on ensuring the legitimacy of control flow in speculative execution. It reuses the microarchitectural side effects of PA and BTI to enforce fine-grained verification of speculative correctness at the branch instruction, the chokepoint for all control-flow attacks. We validated Janus by constructing various leakage gadgets, showing that the defense remained effective regardless of the gadget’s structure. The attack was intercepted at its source, preventing it from reaching the gadget. This demonstrates that Janus offers fundamental, forward-looking protection rather than relying on pattern matching. PACMAN: We also tested Janus’s mitigation of PACMAN attacks, which aim to leak PA metadata. Using the original PoC exploit, we adapted it for our testbed and confirmed its ability to steal a PAC. After applying Janus protection, the exploit failed to steal the PAC, with no cache signal detected.
8
Related Work
Janus draws on the SLH-enhanced method [9, 22, 31] to control speculative execution and enhance protection using memory safety hardware. While FineIBT reduces the speculation window, it doesn’t fully eliminate it. Existing ARM-based Spectre defenses like SpecASan [12] (hardware) and SwitchPotline [2] (software) target specific vulnerabilities. In contrast, Janus provides a comprehensive defense against control-flow related speculative execution attacks, integrating CFI and memory safety mechanisms for stronger, optimized protection.
9
Conclusion
In this paper, we introduced Janus, a security framework that mitigates transient execution attacks using hardware memory safety primitives. By combining Arm PA and BTI, Janus ensures controlflow and data integrity, defending against Spectre variants and PACMAN attacks. Evaluation on ARMv8-A hardware shows Janus provides robust protection with 3.85% average overhead, demonstrating its effectiveness and cross-platform adaptability. Janu offers a scalable, efficient solution for safeguarding against speculative execution vulnerabilities.
Acknowledgments This work was supported in part by the National Key Research and Development Program of China under Grant No. 2024YFE0211100, the Joint Funds of the National Natural Science Foundation of China under Grant No. U24A6009, and the National Science Fund for Distinguished Young Scholars under Grant No. 62125208.
References [1] Enrico Barberis, Pietro Frigo, Marius Muench, Herbert Bos, and Cristiano Giuffrida. 2022. Branch History Injection: On the Effectiveness of Hardware Mitigations Against Cross-Privilege Spectre-v2 Attacks. In 31st USENIX Security Symposium (USENIX Security 22). USENIX Association, Boston, MA, 971–988. https://www.usenix.org/conference/usenixsecurity22/presentation/barberis [2] Markus Bauer, Lorenz Andreas Hetterich, Christian Rossow, and Michael Schwarz. 2024. Switchpoline: A Software Mitigation for Spectre-BTB and Spectre-BHB on ARMv. (2024). [3] Tyler Bletsch, Xuxian Jiang, Vince W Freeh, and Zhenkai Liang. 2011. Jumporiented programming: a new class of code-reuse attack. In Proceedings of the 6th ACM symposium on information, computer and communications security. 30–40. [4] Nathan Burow, Scott A Carr, Joseph Nash, Per Larsen, Michael Franz, Stefan Brunthaler, and Mathias Payer. 2017. Control-flow integrity: Precision, security, and performance. ACM Computing Surveys (CSUR) 50, 1 (2017), 1–33. [5] Nicholas Carlini, Antonio Barresi, Mathias Payer, David Wagner, and Thomas R Gross. 2015. Control-flow bending: On the effectiveness of control-flow integrity. In 24th USENIX Security Symposium (USENIX Security 15). 161–176. [6] Chandler Carruth. 2024. Speculative Load Hardening. Technical Report. [7] Miguel Castro, Manuel Costa, and Tim Harris. 2006. Securing software by enforcing data-flow integrity. In Proceedings of the 7th symposium on Operating systems design and implementation. 147–160. [8] Xiangdong Chen, Zhaofeng Li, Tirth Jain, Vikram Narayanan, and Anton Burtsev. 2024. Limitations and opportunities of modern hardware isolation mechanisms. In 2024 USENIX Annual Technical Conference (USENIX ATC 24). 349–368. [9] Neophytos Christou, Alexander J Gaidis, Vaggelis Atlidakis, and Vasileios P Kemerlis. 2024. Eclipse: Preventing Speculative Memory-error Abuse with Artificial Data Dependencies. In Proceedings of the 2024 on ACM SIGSAC Conference on Computer and Communications Security. 3913–3927. [10] Crispin Cowan, Perry Wagle, Calton Pu, Steve Beattie, and Jonathan Walpole. 2000. Buffer overflows: Attacks and defenses for the vulnerability of the decade. In Proceedings of the DARPA Information Survivability Conference & Exposition. IEEE, 119–129. [11] Luís Fiolhais and Leonel Sousa. 2023. Transient-Execution Attacks: A Computer Architect Perspective. Comput. Surveys 56 (2023), 1 – 38. https: //api.semanticscholar.org/CorpusID:259120377 [12] Saber Ganjisaffar, Esmaeil Mohmmadian Koruyeh, Jason Zellmer, Hodjat Asghari Esfeden, Chengyu Song, and Nael Abu-Ghazaleh. 2025. SpecASan: Mitigating Transient Execution Attacks Using Speculative Address Sanitization. In Proceedings of the 52nd Annual International Symposium on Computer Architecture (ISCA ’25). Association for Computing Machinery, New York, NY, USA, 2032–2045. doi:10.1145/3695053.3731119 [13] Enes Göktas, Kaveh Razavi, Georgios Portokalidis, Herbert Bos, and Cristiano Giuffrida. 2020. Speculative probing: Hacking blind in the Spectre era. In Proceedings of the 2020 ACM SIGSAC Conference on Computer and Communications Security. 1871–1885. [14] Deepak Gupta. 2024. riscv control-flow integrity for usermode. https://lwn.net/ Articles/990220/ [15] Hong Hu, Shweta Shinde, Sendroiu Adrian, Zheng Leong Chua, Prateek Saxena, and Zhenkai Liang. 2016. Data-oriented programming: On the expressiveness of non-control data attacks. In 2016 IEEE Symposium on Security and Privacy (SP). IEEE, 969–986. [16] Intel. 2023. IntelAnalysisofSpeculativeExecutionSideChannels. Technical Report. Intel. [17] Intel Corporation. 2019. Control-flow Enforcement Technology Specification (Revision 3.0). https://kib.kiev.ua/x86docs/Intel/CET/334525-003.pdf [18] Paul Kocher, Jann Horn, Anders Fogh, Daniel Genkin, Daniel Gruss, Werner Haas, Mike Hamburg, Moritz Lipp, Stefan Mangard, Thomas Prescher, et al. 2020. Spectre attacks: Exploiting speculative execution. Commun. ACM 63, 7 (2020), 93–101. [19] Esmaeil Mohammadian Koruyeh, Khaled N. Khasawneh, Chengyu Song, and Nael B. Abu-Ghazaleh. 2018. Spectre Returns! Speculation Attacks Using the Return Stack Buffer. IEEE Design & Test 41 (2018), 47–55. https://api.semanticscholar. org/CorpusID:49901800 [20] ARM Ltd. 2022. ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile. ARM Ltd. https://developer.arm.com/documentation/ddi0487/latest [21] Arm Ltd. 2023. Arm A-profile Architecture: Feature Description – FEAT_FPAC (Faulting on Pointer Authentication failures). Technical Report. Arm Ltd. Accessed: YYYY-MM-DD. [22] Tiziano Marinaro, Pablo Buiras, Andreas Lindner, Roberto Guanciale, and Hamed Nemati. 2024. Beyond Over-Protection: A Targeted Approach to Spectre Mitigation and Performance Optimization. In Proceedings of the 19th ACM Asia Conference on Computer and Communications Security. 203–216. [23] Matt Miller. 2019. Trends and challenges in the vulnerability mitigation landscape. USENIX Association (2019). [24] PaX Team. 2003. PaX Address Space Layout Randomization (ASLR). https: //pax.grsecurity.net/docs/aslr.txt
[25] Marios Pomonis, Theofilos Petsios, Angelos Dennis Keromytis, Michalis Polychronakis, and Vasileios P. Kemerlis. 2017. 𝑘𝑅𝑋 : Comprehensive Kernel Protection against Just-In-Time Code Reuse. Proceedings of the Twelfth European Conference on Computer Systems (2017). https://api.semanticscholar.org/CorpusID: 592404 [26] Joseph Ravichandran, Weon Taek Na, Jay Lang, and Mengjia Yan. 2022. PACMAN: attacking ARM pointer authentication with speculative execution. In Proceedings of the 49th Annual International Symposium on Computer Architecture. 685–698. [27] Ryan Roemer, Erik Buchanan, Hovav Shacham, and Stefan Savage. 2012. Returnoriented programming: Systems, languages, and applications. ACM Transactions on Information and System Security (TISSEC) 15, 1 (2012), 1–34. [28] Marc Schink and Johannes Obermaier. 2019. Taking a Look into Execute-Only Memory. ArXiv abs/1909.05771 (2019). https://api.semanticscholar.org/CorpusID: 201803787 [29] Felix Schuster, Thomas Tendyck, Christopher Liebchen, Lucas Davi, Ahmad-Reza Sadeghi, and Thorsten Holz. 2015. Counterfeit object-oriented programming: On the difficulty of preventing code reuse attacks in C++ applications. In 2015 IEEE Symposium on Security and Privacy. IEEE, 745–762. [30] Xi Tan, Sagar Mohan, Md. Armanuzzaman, Zheyuan Ma, Gaoxiang Liu, Alex Eastman, Hongxin Hu, and Ziming Zhao. 2024. Is the Canary Dead? On the Effectiveness of Stack Canaries on Microcontroller Systems. Proceedings of the 39th ACM/SIGAPP Symposium on Applied Computing (2024). https://api. semanticscholar.org/CorpusID:269951615 [31] Marco Vassena, Craig Disselkoen, Klaus von Gleissenthall, Sunjay Cauligi, Rami Gökhan Kıcı, Ranjit Jhala, Dean Tullsen, and Deian Stefan. 2021. Automatically eliminating speculative leaks from cryptographic code with blade. Proceedings of the ACM on Programming Languages 5, POPL (2021), 1–30. [32] Sander Wiebing, Alvise de Faveri Tron, Herbert Bos, and Cristiano Giuffrida. 2024. { InSpectre } Gadget: Inspecting the Residual Attack Surface of Cross-privilege Spectre v2. In 33rd USENIX Security Symposium (USENIX Security 24). 577–594. [33] Wenjie Xiong and Jakub Szefer. 2021. Survey of Transient Execution Attacks and Their Mitigations. ACM Computing Surveys (CSUR) 54 (2021), 1 – 36. https: //api.semanticscholar.org/CorpusID:235348755