Google Project Zero has published the second installment of its Pixel 9 zero-click exploit chain research, detailing how a kernel driver for the on-chip BigWave AV1 hardware accelerator can be abused to escape the mediacodec SELinux sandbox and achieve arbitrary kernel read/write on a fully patched Pixel 9. Fixes for all three reported bugs were shipped on January 5, 2026.

From Mediacodec to the Kernel

The research began by mapping which kernel drivers are reachable from the mediacodec SELinux context, the constrained environment used for non-secure software decoders. Using a custom tool called DriverCartographer, the researcher identified /dev/bigwave as accessible from that context. BigWave is hardware integrated into the Pixel SoC to accelerate AV1 decoding, which explains its exposure to the media processing context.

A few hours of code auditing turned up three distinct bugs in the BigWave driver.

  • Bug 1: A duplicate of a vulnerability originally reported in February 2024. Despite the fix requiring only a two-line transposition, it remained unpatched at the time of rediscovery in June 2025, more than a year later.
  • Bug 2: A novel bug class analogous to the double-free kmalloc exploitation primitive, but operating on a different linked list.
  • Bug 3: A use-after-free (UAF) that produces a reliable arbitrary write primitive without requiring a KASLR leak.

The Use-After-Free in Detail

Every time /dev/bigwave is opened, the driver allocates a per-instance kernel struct (inst) stored in the file descriptor’s private_data field. An inline sub-struct called job tracks register values and execution status for each hardware invocation.

Submitting work via the BIGO_IOCX_PROCESS ioctl places a job on a priority queue consumed by a separate kernel thread, bigo_worker_thread. The ioctl then blocks for up to 16 seconds waiting for job completion. If the timeout expires before the worker signals completion, the ioctl dequeues the job and returns to userland. However, under queue pressure, the worker thread may have already dequeued and begun processing that same job concurrently.

If userland then closes the file descriptor, the inst struct (and the embedded job) is freed while bigo_worker_thread continues to access it. The critical window occurs inside bigo_run_job: the function sets BigWave processor registers at the start, waits up to one second for frame completion, and then calls bigo_pull_regs, which performs a memcpy_fromio into the address stored at job->regs. By the time this copy occurs, both inst and job have been freed.

Turning UAF into Arbitrary Write

By spraying attacker-controlled allocations over the freed region (for example via Unix Domain Socket messages), an attacker can overwrite job->regs with an arbitrary pointer. Because the register state is set before hardware execution begins, and because the hardware can be directed not to execute at all, the end register state closely mirrors the initial state. The result is a roughly 2,144-byte write to an attacker-controlled destination using attacker-controlled content.

Notably, this primitive does not require defeating KASLR to be useful, though the researcher notes that KASLR bypass would still be possible by reallocating a suitable kernel object over the freed inst.

Takeaways

The research reinforces a recurring theme in Android security: hardware accelerator drivers reachable from media processing contexts are high-value targets for privilege escalation. The persistence of a known, trivially fixable bug for more than a year in a shipping driver underscores the importance of tracking patch status across the full SoC driver stack, not just upstream AOSP components.