Papers
Topics
Authors
Recent
Search
2000 character limit reached

Cage: Memory Tagging & Pointer Authentication

Updated 27 June 2026
  • Cage is a framework that utilizes hardware-assisted memory tagging and pointer authentication to provide fine-grained spatial, temporal, and control-flow safety.
  • It instruments memory management by embedding randomized MTE tags for allocations and employing PAC to safeguard pointer integrity with minimal overhead.
  • Cage supports authenticated data structures through cryptographic MAC chaining, ensuring that any memory tampering is detected or aborts operation.

Cage refers to a set of mechanisms and toolchains that utilize hardware-assisted memory tagging and pointer authentication to enforce fine-grained memory safety and integrity within contemporary processor-based systems, notably in high-assurance runtime environments such as WebAssembly. Derived chiefly from Arm’s Memory Tagging Extension (MTE) and Pointer Authentication (PAC), Cage embodies a minimally invasive framework for integrating spatial, temporal, and control-flow safety into high-performance in-memory data structures and low-level system runtimes, with modest performance overhead and compatibility with unmodified, low-level code (Ghorshi et al., 2022, Fink et al., 2024).

1. Hardware Mechanisms: Arm MTE and PAC

Arm’s MTE provides 4-bit tags per 16-byte granule, stored in bits [59:56] of 64-bit pointers and a side-channel tag memory. On MTE-enabled hardware, memory accesses verify that the tag embedded in the pointer matches the tag in tag memory; on mismatch, a hardware fault is signaled. Tagged pointers are formed at allocation time using a randomized, nonzero tag value, and memory region tags are set accordingly. MTE enforces spatial safety (bounds overflows are detected as tag mismatches) and can be engineered to provide temporal safety via tag randomization and poisoning on deallocation, preventing use-after-free and double-free vulnerabilities. Tag granularity (16 bytes) implies a 1/15 probabilistic collision risk per allocation (with tag 0 as reserved) (Fink et al., 2024).

Arm’s PAC implements a 32-bit message authentication code (MAC) over the pointer value and a context modifier using per-register key material, producing a signed pointer with embedded authentication bits. On pointer use (e.g., indirect call), the PAC is verified; mismatches trigger faults. PAC-based pointer authentication provides integrity against pointer substitution and reuse, and in the Cage implementation, integrates with memory management and function-pointer storage to harden control-flow (Fink et al., 2024).

2. Compiler and Runtime Instrumentation

Cage extends the LLVM toolchain for WebAssembly (wasm64) to instrument memory management and control-flow as follows (Fink et al., 2024):

  • Each heap allocation via malloc, realloc, or free is transformed to include setting or clearing of MTE tags (segment.new, segment.free). Pointers returned to application code embed the corresponding tag.
  • Stack allocations are similarly instrumented: on function entry, a random tag is selected for the stack frame, and slots are tagged by offset. On return, slots are “poisoned” with a fresh tag to enforce temporal safety. Guard granules with disjoint tags separate adjacent stack slots.
  • Indirect function calls and pointer stores are instrumented with PAC sign and verify instructions, ensuring integrity of function pointer use. The instrumentation ensures that only authenticated pointers can be dereferenced for calls, preventing cross-instance and cross-sandbox pointer reuse.

The Cage runtime (e.g., in wasmtime) parses these extended instructions and lowers them to corresponding AArch64 hardware operations (irg, stg, pacda, autda, etc.). On module instantiation, each instance receives random MTE and PAC modifiers, providing per-instance compartmentalization (Fink et al., 2024).

3. Authenticated Data Structures and Tagging Schemes

Cryptographically-authenticated in-memory data structures (e.g., authenticated stacks and queues) leverage hardware-assisted tag or MAC chaining to guarantee that any tampering with memory is either detected or aborts operation.

  • With Intel AES-NI, a 128-bit AES-CMAC is used to tag data (tag width b=128b=128); with Arm PAC, hardware computes a 32-bit MAC (tag width b=32b=32). The tag computation formula is

Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})

and verification replaces tag checks on every access.

  • For stacks, each element ii is stored as {di,nonce,tagi}\{d_i, \mathrm{nonce}, \mathrm{tag}_i\}, and the tags are computed via chained MACs:

MACi=MACK(H(di)nonceiMACi1)\mathrm{MAC}_i = \mathrm{MAC}_K(H(d_i) \| \mathrm{nonce} \| i \| \mathrm{MAC}_{i-1})

The top of the stack tag implicitly vouches for the authenticity of all previous elements through this cryptographic chain.

  • For queues, element tags and a global state tag are maintained:

State:S=MACK(nonceibif)\mathrm{State}: S = \mathrm{MAC}_K(\mathrm{nonce} \| i_b \| i_f)

ElemTagj=MACK(H(dj)noncej)\mathrm{ElemTag}_j = \mathrm{MAC}_K(H(d_j) \| \mathrm{nonce} \| j)

Verification checks these invariants at enqueue, dequeue, and access operations.

Arbitrary authenticated data structures can be constructed by layering, for example, a Merkle tree over a memory region, enabling O(logN)O(\log N) authenticated random access, while dedicated chain constructions yield O(1)O(1) operations for stacks and queues with cryptographic sequence (Ghorshi et al., 2022).

4. Threat Model, Security Objectives, and Correctness

The threat model assumes an adversary that controls all program memory (arbitrary read/write) except for code bytes and registers, constrained only by Wb=32b=320 and coarse-grained CFI. Three adversary strengths are detailed: multi-threaded race-capable (Adv-Fast), race-limited (Adv-Slow), and single-thread at-vulnerability (Adv-Single). The goal is that authenticated data structures (ADS) either follow their intended semantics or detect tampering and trap.

Correctness and security proofs reduce the adversary’s success to finding a collision in the underlying MAC function. For stacks, any adversary able to swap elements undetected must induce a MAC collision—e.g., on b=32b=321 vs. b=32b=322. For queues, both index and data swapping reduce to similar games. The adversary’s overall success probability is bounded by b=32b=323 (b=32b=324 is tag/MAC width), or b=32b=325 for guessing a new tag, where b=32b=326 is the number of queries; for PAC it is upper bounded by b=32b=327, for CMAC by b=32b=328 (Ghorshi et al., 2022).

5. Performance and Overhead Analysis

Cage incurs minimal runtime and memory overheads in real workloads:

  • On full memory-safety-sandbox-ptr-auth configurations, runtime overhead is measured at b=32b=329 on out-of-order Arm cores; memory overhead is Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})0 (including 3.125% for tag memory). For in-order cores, offloading sandbox bounds checks can yield Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})1 speedup.
  • Microbenchmarks on authenticated data structures reveal Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})2 overhead per operation for micro-scale stack/queue operations, but amortized geometric mean overhead in real OpenCV workloads is Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})3 (intensive usage) and up to Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})4 with smart pointers, as per-operation costs are dominated by batch or larger workloads.
  • Sandboxing with hardware tagging provides speedups compared to the traditional software bounds-checks approach: Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})5 on big cores, Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})6 on little cores.
  • PAC sign/auth operation cost is negligible, about Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})7 cycles per invocation (Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})8 total overhead) (Fink et al., 2024, Ghorshi et al., 2022).

6. Design Trade-offs and Limitations

Trade-offs in Cage-based authenticated memory tagging arise due to tag size versus collision probability, and resource partitioning:

  • MTE’s 4-bit tags (16 possible values) entail a Tag=MACK(payloadopaque_metadata)\mathrm{Tag} = \mathrm{MAC}_K(\text{payload} \| \text{opaque\_metadata})9 tag-collision probability if many live allocations share tags. Integrating both sandboxing and memory safety by partitioning tag bits (e.g., bit[56] for sandboxing, bits[59:57] for user tags) increases collision frequency to ii0 per granule.
  • PAC’s 32-bit tags permit up to ii1 probability of undetected forgery per check, sufficient for ephemeral or low-value data. For higher integrity, AES-CMAC with 128-bit tags (AES-NI) reduces collision risk to ii2 but at greater computation cost.
  • The number of Cage instances (sandboxes) per process is limited by tag space; at most ii3 can co-exist (one tag reserved for runtime).
  • A plausible implication is that large-scale, highly-compartmentalized runtimes may confront tag exhaustion, limiting parallelism or requiring multi-process architectures.
  • PAC keys are held per process; Cage uses a per-instance random modifier to prevent pointer reuse across sandboxes or processes (Fink et al., 2024, Ghorshi et al., 2022).

7. Integration and Future Directions

Cage generalizes authenticated in-memory data structure techniques by proposing the folding of authentication tags into architectural metadata (e.g., using high-order bits in MTE, side-channel metadata, or heap header fields). Recursive ADS can store state tags of multiple sub-structures, reducing the trusted tag surface to a single register. Integration of memory tagging into language runtimes and system allocators enables drop-in secure data structures for standard containers (e.g., std::stack, std::queue) with minimal developer intervention.

Future architectural and compiler support (including C++ attribute extensions to mandate register pinning or inlining of tag operations) would strengthen resistance to advanced attacks (e.g., Adv-Fast multi-thread races). A plausible implication is that future instruction set enhancements and toolchain improvements could broaden the applicability of authenticated data structures to persistent data, distributed scenarios, and more granular compartmentalization (Ghorshi et al., 2022, Fink et al., 2024).

Definition Search Book Streamline Icon: https://streamlinehq.com
References (2)

Topic to Video (Beta)

No one has generated a video about this topic yet.

Whiteboard

No one has generated a whiteboard explanation for this topic yet.

Follow Topic

Get notified by email when new papers are published related to Cage—Memory Tagging and Authentication.