Skip to content

Build2 publishers2 min readPublished

VUSec's BTR reuses a branch-target entry that outlives the JIT code it pointed to

VUSec disclosed Branch Target Reuse, a Spectre-v2 attack on JIT engines whose Linux exploit leaks memory at 8 bytes a second. It bypassed every enabled mitigation, and the kernel's fix had already shipped in July.

The Engineer · Build desk

Photograph accompanying VUSec's BTR reuses a branch-target entry that outlives the JIT code it pointed to
Photo: phoronix.com

What happened

  • Modern processors restore architectural coherence after self-modifying code but leave the stale indirect-branch predictions that once pointed at it sitting in the predictor.
  • Inside a JIT, that stale target outlives the freed code and gets reused when the cache is repopulated, so the CPU speculatively runs whatever used to live at that offset.
  • VUSec analyzed Linux cBPF, Oracle's GraalVM and Firefox's SpiderMonkey, and built two full exploits against the Linux kernel.
  • The Linux demo pulls the root password hash out of a running su process by walking the kernel task list and then the page tables.
  • Every processor the team evaluated was affected, including Intel, AMD and Arm hardware.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint The primitive lives in the branch predictor, not the executable code, so JIT defenses that rewrite or mask the generated code do not stop it.
  • decision Each affected project chose its own mitigation, so a shop running these JITs has to adopt and benchmark three unrelated changes, one per runtime.
  • exposure Until Firefox finishes deploying site isolation, a malicious page's JavaScript shares an address space with other tabs, putting their data within reach.

The kernel's answer shipped before the public write-up. BTR was privately disclosed in July [13], and Phoronix reports the Linux kernel then landed patches enabling an Indirect Branch Predictor Barrier flush on every BPF JIT allocation, plus hardening against JIT spraying [14]. Those changes were mainlined and backported to stable kernels, so the public disclosure arrives with no new kernel mitigation attached [14]. IBPB flushes the branch predictor. The stale target lives there, and software hardening inside the JIT never reaches it [2].

That gap is clearest in cBPF. The bpf_jit_harden option blinds immediate constants to block direct JIT spraying, and it is off by default [8]. Even so, VUSec got past it by encoding instructions in jump offsets, the first time that spraying technique has been applied to cBPF [8]. GraalVM goes further: its strictest sandbox masks every guest memory access so the code cannot reach outside its arena [11]. BTR gets past that too, because the speculative jump lands on the obsolete entry point before any of those checks run [3].

The working exploit is slow but sufficient. The cBPF leak runs at 8 bytes per second, and VUSec's point is that careful pointer chasing needs only a small amount of leaked data to reach the secret [6]. SpiderMonkey is earlier work. The proof of concept speculatively jumps into the WebAssembly literal pool, and on Intel the team confirmed that branch-target buffer entries survive a full deallocate-and-reallocate cycle, at an estimated tens of bytes per second; a real browser exploit still needs more work [10].

By Phoronix's account, the three affected projects took three paths. The kernel took the IBPB barrier [14]. Oracle is randomizing GraalVM's JIT code-cache locations so a freed chunk and its replacement are less likely to share an address [15]. Mozilla evaluated IBPB for SpiderMonkey and decided against it, prioritizing site isolation instead [16]. The chip vendors are pointing operators to existing mitigation mechanisms [17]. None of this material puts a performance number on any of these options.

What to watch

  • Whether VUSec's SpiderMonkey proof of concept becomes a working end-to-end browser exploit.
  • Published performance figures for the IBPB-on-JIT-allocation flush and GraalVM code-cache randomization.
  • Whether JIT runtimes beyond the three VUSec analyzed adopt IBPB flushes or code-cache randomization.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories