Home · ASPLOS 2025 · Operating Systems & Virtualization

Segue & ColorGuard: Optimizing SFI Performance and Scalability on Modern Architectures

Shravan Narayan, Tal Garfinkel, Evan Johnson, Zachary Yedidia, Yingchen Wang, Andrew Brown and 7 others

Conference
ASPLOS 2025
Published
2025
Pages
987-1002
Citations
1

WebAssembly sandboxes untrusted code inside a process using software fault isolation — the compiler adds a base address to every memory access so the code can only touch its own region — but that extra addition on every access costs speed and ties up a register, and the huge guard regions used to skip bounds checks waste so much address space that few sandboxes fit in one process; this paper (UC San Diego, Intel and collaborators — Shravan Narayan, Tal Garfinkel, Deian Stefan, Dean M. Tullsen, and others) presents two optimizations, Segue and ColorGuard — Segue puts the sandbox base in an x86-64 segment register so the addressing hardware does the addition for free, eliminating 44.7 percent of Wasm's overhead, and ColorGuard uses memory tagging (Intel MPK) to reclaim the wasted address space, packing up to 15 times more Wasm instances into one process.

The argument in one glance

  1. Problem

    Sandboxing code in one process is cheap in theory, but taxes every memory access

    Software fault isolation (SFI) lets you run untrusted code safely inside your own process, without the cost of a separate process, by having the compiler instrument every memory access so the code can only touch its own sandbox region. This is the backbone of WebAssembly (Wasm), which is used to sandbox plugins in browsers and untrusted functions on servers. But the instrumentation is not free. To confine an access, the compiler must combine the sandbox's base address with the code's offset on every load and store, and it must reserve address space so out-of-bounds accesses can be caught. Those two requirements, repeated across a whole program and across many sandboxes, turn into a real performance tax and a real scalability ceiling — and both get worse the more you rely on Wasm.

  2. What people did

    Add the base on every access and reserve a big guard region

    The standard Wasm sandboxing scheme does two things. For performance, each memory access computes its address as the sandbox's linear-memory base (the heap base) plus a 32-bit offset; the compiler emits an instruction to add the base, kept in a register, before the access. For safety without a bounds-check on every access, each sandbox reserves a large region — typically 4 gigabytes of usable memory plus a 4-gigabyte guard region, 8 gigabytes total — so any address the 32-bit offset can form either lands in the sandbox or in the guard region, where the hardware faults.

  3. Why it fell short

    The base addition is slow and the guard regions waste the address space

    Both mechanisms are costly. The base addition happens on every single memory access: it is an extra instruction, and it ties up a register (holding the heap base) and an operand slot that the compiler could otherwise use, so it slows the sandboxed code throughout. Separately, reserving 8 gigabytes of virtual address space per sandbox, most of it an unused guard region, means a single process can only hold a limited number of Wasm instances before it runs out of address space. Server-side and edge platforms are already hitting this ceiling, forcing them into multi-process architectures that hurt throughput and latency and add complexity. So SFI as deployed leaves performance on the table on every access and cannot scale to the density that high-volume Wasm workloads demand — two separate problems rooted in how the sandbox is addressed and how its bounds are enforced.

  4. This paper's idea

    Let hardware do the base addition, and tag memory to reclaim the guard space

    This paper presents two independent optimizations that use existing x86-64 hardware. Segue attacks the per-access cost by using segmentation: x86-64 still has the FS and GS segment registers, and an access made relative to a segment register automatically adds that register's base to the address as part of the load or store. So Segue stores the sandbox's heap base in the GS segment register and uses segment-relative addressing, so the base addition happens for free in the addressing hardware — one instruction instead of two — and it frees up the register and operand slot the compiler had been spending. This eliminates 44.7 percent of Wasm's overhead on a Wasm-compatible subset of SPEC CPU 2006 and cuts Wasm-sandboxed font-rendering overhead in Firefox by 75 percent. ColorGuard attacks the scalability limit by using memory tagging, such as Intel Memory Protection Keys (MPK): instead of giving each sandbox its own guard region that wastes address space, it assigns each instance a unique tag (a color) so many instances can share the address space while staying isolated by their tags, reclaiming the wasted space and enabling up to a 15-times increase in concurrent Wasm instances per process. The paper also works through deploying both in three production toolchains: Wasm2c, WAMR, and Wasmtime.

Why this problem is worth solving

WebAssembly has become a standard way to run untrusted code safely and portably, so the cost of its isolation is felt everywhere it is used.

Software fault isolation is a way to sandbox untrusted code inside the same process as the trusted code that hosts it, rather than paying to put it in a separate process. The compiler instruments the untrusted code so that every memory access is confined to a designated region — the sandbox — and cannot read or write the host’s memory. Because it is in-process, calling into and out of the sandbox is cheap, which is why it is attractive for fine-grained isolation: a browser sandboxing a font-rendering library, a server sandboxing thousands of small untrusted functions. WebAssembly is the modern embodiment of this idea; it defines a portable sandboxed instruction set whose isolation is enforced, when compiled to native code, by exactly this kind of instrumentation. Wasm is now used far beyond the browser — in content delivery, edge computing, serverless platforms, and inside applications like Firefox to isolate risky libraries. The consequence is that the overhead of SFI is paid across an enormous and growing amount of computation, so even a modest reduction in per-access cost, or an increase in how many sandboxes fit on a machine, translates into real savings at scale. That is why optimizing SFI is not a niche concern but a lever on the efficiency of a widely deployed isolation mechanism, which is what this paper sets out to pull.

The reason both costs are stubborn is that they come from how the sandbox is addressed, not from wasteful implementation.

Consider how a Wasm memory access works. Wasm load and store instructions take offsets into the sandbox’s linear memory, and the runtime must translate an offset into a real machine address by adding the sandbox’s base address — where that sandbox’s memory actually lives. On a conventional design, the compiler holds the base in a register and emits an add before each access, so every load and store carries an extra instruction plus the register and operand slot that base occupies. This is not sloppiness; it is the fundamental work of relocating an offset into the right region, done on every access. The second cost, guard regions, comes from wanting to avoid an explicit bounds check on every access, which would be even more expensive. Instead, because Wasm offsets are 32-bit, the runtime reserves enough address space (the 4-gigabyte usable region plus a 4-gigabyte guard region) that any address a 32-bit offset can produce is either valid or lands in the guard region, where the memory management unit faults — turning a bounds check into a passive hardware trap. That is elegant for safety but profligate with address space: 8 gigabytes reserved per sandbox, mostly never touched. Both costs are inherent to translating and bounding a sandboxed access in software, which is why relieving them requires enlisting hardware features that can do the relocation and the bounding for free, rather than merely coding the software more cleverly.

What people did before, and where it broke

  • Explicit bounds checks on every access. Insert a comparison before each load and store to confirm it is in range. Where it broke. A check on every access is expensive, which is exactly why Wasm moved to guard regions instead; it trades one overhead for another.
  • Guard regions to avoid bounds checks. Reserve a large usable-plus-guard region per sandbox so out-of-bounds accesses fault in hardware. Where it broke. It removes per-access checks but consumes about 8 gigabytes of virtual address space per sandbox, so only a limited number of instances fit in a process, capping scalability.
  • Base addition in a general-purpose register. Keep the sandbox’s heap base in a register and add it before each access. Where it broke. It costs an instruction on every access and permanently occupies a register and an operand slot the compiler could use, taxing performance throughout the code.
  • Multi-process isolation for scale. When one process cannot hold enough sandboxes, spread them across processes. Where it broke. Multiple processes sacrifice the low-latency, high-throughput, cheap-transition benefits that made in-process SFI attractive, and add operational complexity.
  • The gap. No deployed scheme used modern x86-64 hardware to make the base addition free and to reclaim the address space wasted by guard regions, so SFI kept paying a per-access performance tax and a per-sandbox address-space tax that ordinary software optimization could not remove.

How Segue and ColorGuard work

Using x86-64 segmentation and memory tagging to speed up and scale SFI

  1. new

  2. new

  3. new

  4. new

  5. new

The idea

Offload the per-access base addition to the addressing hardware. Segue’s insight is that the extra add on every memory access is not really computation the CPU needs a separate instruction for — it is exactly what segment-relative addressing already does. x86-64 kept the FS and GS segment registers, and any access relative to one of them has the segment base added automatically as the address is formed. So Segue holds the sandbox’s heap base in the GS register and addresses through it, and the relocation that used to be an explicit instruction becomes a free side effect of the load or store, also freeing the general-purpose register and operand slot the base had monopolized. Making a security mechanism nearly free by having existing hardware enforce it, rather than spending software instructions on every operation, is the same efficiency-through-hardware instinct the work on a protected services framework using confidential-computing hardware covered elsewhere on this site relies on, letting the hardware carry the isolation. Segue applies it to the humblest, most frequent operation — the memory access — which is why removing its overhead pays off so broadly.

Keep the isolation guarantee while removing its instruction. The subtle part is that Segue must not weaken safety: the sandbox still has to be confined. It preserves the guarantee because segment-relative addressing still combines the trusted base (which the untrusted code cannot change) with the offset, so the access still lands in the sandbox, and the guard-region trap still catches out-of-bounds offsets. Only the cost moves, not the security. Providing strong software isolation efficiently, so untrusted code can run in-process without a heavy per-operation price, is the same goal the work on practical, efficient, and secure software sandboxing covered elsewhere on this site pursues, driving the overhead of fault isolation toward zero. Segue advances that goal by finding an underused hardware feature that does the sandbox’s addressing work for free, delivering what the paper describes as the largest reduction in SFI overhead on x86-64 in two decades.

Reclaim the address space that guard regions waste, using tags. ColorGuard tackles a different scarcity: virtual address space. Guard regions make bounds checks free but leave most of each sandbox’s reserved 8 gigabytes untouched, so the process runs out of address space long before it runs out of memory or compute, capping how many sandboxes fit. ColorGuard uses memory tagging to enforce isolation by color instead of solely by a private padded range, so many instances can coexist in the space guard regions used to squander, packing up to fifteen times more per process. Reclaiming capacity that a rigid, worst-case reservation had stranded, so far more work fits in the same resource, is the same principle the work on memory pooling to recover stranded capacity covered elsewhere on this site is built on, turning wasted headroom into usable density. ColorGuard recovers stranded virtual address space, which is exactly the resource that limits Wasm density at scale.

Following a memory access through Segue

Confining a sandboxed load, and packing many sandboxes in one process

A trace, drawn from the paper, of how Segue makes a memory access cheap and how ColorGuard packs sandboxes densely.

Step 1 of 5

Sandboxed code issues a memory access

Untrusted Wasm code performs a load or store using a 32-bit offset into its linear memory. The runtime must turn that offset into a real machine address confined to the sandbox's region.

Every load and store needs this relocation, so its cost is paid constantly.

Why it works

  • Segment addressing already computes base plus offset. Adding the base in a general-purpose register costs an instruction every access → but segment-relative addressing folds that addition into the load or store → so the relocation becomes free while still confining the access.
  • Freeing a register and slot helps the whole program. Pinning the heap base in a register denies it to the compiler throughout → but Segue moves the base into a segment register → so the compiler regains a register and operand slot, speeding code beyond just the removed add.
  • Safety is unchanged because the trusted base still applies. A faster access is worthless if it escapes the sandbox → but segment addressing still combines the untrusted offset with the trusted base and the guard trap still fires → so isolation holds exactly as before.
  • Tags enforce isolation without a private padded range. Guard regions reserve gigabytes per sandbox to bound accesses → but a per-instance memory tag isolates instances that share address space → so the wasted guard space can be reclaimed for more sandboxes.
  • Reclaimed address space is what caps Wasm density. Processes run out of virtual address space before memory or compute → but ColorGuard recovers the space guard regions squandered → so up to fifteen times more instances fit, relieving the real scaling bottleneck.

What it costs (trade-offs and scope)

  • Segue depends on x86-64 segmentation and cheap segment-register writes. The optimization is specific to architectures with usable segment registers; on x86-64 it wants the FSGSBASE extension for cheap user-level writes to the segment base, and without it must fall back to a system call whose overhead must be carefully managed. Other architectures would need an analogous feature.
  • ColorGuard depends on memory tagging hardware. It relies on memory protection keys (Intel MPK) or an equivalent; the paper notes ARMv9’s permission overlay extension should work similarly but could not be evaluated because hardware and emulators do not yet support it, so today the benefit is tied to specific hardware.
  • Tag-based isolation must be applied carefully to stay secure. Packing sandboxes and striping protection-key slots to cover guard-region sizes must not introduce new vulnerabilities such as out-of-bounds accesses slipping between instances; the paper addresses this, but it is a correctness burden that ordinary guard regions did not impose.
  • Deployment into real toolchains is nontrivial. The paper explicitly explores the challenges of integrating both optimizations into Wasm2c, WAMR, and Wasmtime; the gains are real but require toolchain work, and the ease and exact benefit vary by toolchain.
  • The reported numbers are for specific workloads and hardware. Eliminating 44.7 percent of Wasm overhead, cutting Firefox font-rendering overhead by 75 percent, and enabling up to a 15-times instance increase are measured on particular benchmarks (a Wasm-compatible subset of SPEC CPU 2006, Firefox, server-side workloads) and hardware; other programs and machines would differ.

The evaluation

Running WebAssembly sandboxes on x86-64

PropertyBaseline SFISegueColorGuard
Base addition per access
Register and operand slot
Address space per sandbox
Concurrent instances per process
Reported outcome
A qualitative comparison of the two optimizations against baseline SFI. Segue eliminates 44.7 percent of Wasm's overhead on a Wasm-compatible SPEC CPU 2006 subset (and 75 percent of Firefox font-rendering overhead); ColorGuard enables up to a 15-times increase in concurrent Wasm instances per process. The two are independent and can be combined.Underlined values explain themselves when clicked.

Check yourself

Check your understanding

  1. 1. What two costs does standard software fault isolation impose on WebAssembly on x86-64?

  2. 2. How does Segue eliminate the per-access base-addition cost?

  3. 3. How does ColorGuard increase how many Wasm instances fit in one process?

  4. 4. What did the paper achieve, and what are the main caveats?

Sources

The paper is “Segue & ColorGuard: Optimizing SFI Performance and Scalability on Modern Architectures” by Shravan Narayan, Tal Garfinkel, Evan Johnson, Zachary Yedidia, Yingchen Wang, Andrew Brown, Anjo Vahldiek-Oberwagner, Michael LeMay, Wenyong Huang, Xin Wang, Mingqiu Sun, Dean M. Tullsen, and Deian Stefan (University of California San Diego, Intel, and collaborators), published at ASPLOS 2025, DOI 10.1145/3669940.3707249. It is licensed CC BY.

This explainer is written from the paper’s full text (the authors’ PDF of the ASPLOS 2025 paper). The paper presents two optimizations that improve the performance and scalability of software fault isolation, the in-process isolation mechanism (built by compiler instrumentation of memory accesses) that underpins WebAssembly. Segue uses x86-64 segmentation to reduce the cost of instrumentation on memory accesses: it stores the sandbox’s linear-memory base in a segment register and uses segment-relative addressing so the processor adds the base for free, eliminating the explicit add instruction and freeing a general-purpose register and operand slot; it eliminates 44.7 percent of Wasm’s overhead on a Wasm-compatible subset of SPEC CPU 2006 and reduces the overhead of Wasm-sandboxed font rendering in Firefox by 75 percent. ColorGuard leverages memory tagging (such as Intel Memory Protection Keys) to assign each Wasm instance a unique tag and reclaim the virtual address space wasted by guard regions, enabling up to a 15-times increase in the number of Wasm instances that can run concurrently in a single address space, improving efficiency for high-scale server-side workloads. The paper also explores the challenges of deploying these optimizations in three production toolchains: Wasm2c, WAMR, and Wasmtime, including hardware dependencies such as the FSGSBASE extension for cheap segment-register writes and the memory-tagging support ColorGuard requires. No numbers beyond the paper’s own have been introduced; exact instruction sequences, the protection-key striping scheme, the toolchain integration, and the full evaluation should be confirmed in the paper.

Related papers on Operating Systems & Virtualization

See all 170 →