Skip to main content
Press slash or control plus K to focus the search. Use the arrow keys to navigate results and press enter to open a threat.
Reconnecting to live updates…

A 0-click exploit chain for the Pixel 9 Part 2: Cracking the Sandbox with a Big Wave

0
Low
Published: 01/14/2026 (01/14/2026, 18:00:00 UTC)
Source: Google Project Zero

Description

With the advent of a potential Dolby Unified Decoder RCE exploit, it seemed prudent to see what kind of Linux kernel drivers might be accessible from the resulting userland context, the mediacodec context. As per the AOSP documentation , the mediacodec SELinux context is intended to be a constrained (a.k.a sandboxed) context where non-secure software decoders are utilized. Nevertheless, using my DriverCartographer tool, I discovered an interesting device driver, /dev/bigwave that was accessible from the mediacodec SELinux context. BigWave is hardware present on the Pixel SOC that accelerates AV1 decoding tasks, which explains why it is accessible from the mediacodec context. As previous research has copiously affirmed , Android drivers for hardware devices are prime places to find powerful local privilege escalation bugs. The BigWave driver was no exception - across a couple hours of auditing the code, I discovered three separate bugs, including one that was powerful enough to escape the mediacodec sandbox and get kernel arbitrary read/write on the Pixel 9. The (Very Short) Bug Hunt The first bug I found was a duplicate that was originally reported in February of 2024 but remained unfixed at the time of re-discovery in June of 2025, over a year later, despite the bugfix being a transposition of two lines of code. The second bug presented a really fascinating bug-class that is analogous to the double-free kmalloc exploitation primitive - but with a different linked list entirely. However it was the third bug I discovered that created the nicest exploitation primitive. Fixes were made available for all three bugs on January 5, 2026. The Nicest Bug Every time the /dev/bigwave device is opened, the driver allocates a new kernel struct called inst which is stored in the private_data field of the fd . Within the inst is a sub-struct called job , which tracks the register values and status associated with an individual invocation of the BigWave hardware to perform a task. In order to submit some work to the bigo hardware, a process uses the ioctl BIGO_IOCX_PROCESS , which fetches Bigwave register values from the ioctl caller in AP userland, and places the job on a queue that gets picked up and used by a separate thread, the bigo worker thread. That means that an object whose lifetime is inherently bound to a file descriptor is transiently accessed on a separate kernel thread that isn’t explicitly synced to the existence of that file descriptor. During BIGO_IOCX_PROCESS ioctl handling, after submitting a job to get executed on bigo_worker_thread , the ioctl call enters wait_for_completion_timeout with a timeout of 16 seconds waiting for bigo_worker_thread to complete the job. After those 16 seconds, if bigo_worker_thread has not signaled job completion, the timeout period ends and the ioctl dequeues the job from the priority queue. However, if a sufficient number of previous jobs were stacked onto the bigo_worker_thread , it is possible that bigo_worker_thread was so delayed that it has only just dequeued and is concurrently processing the very job that the ioctl has considered to have timed out and is trying to dequeue. The syscall context in this case simply returns back to userland, and if at this point userland closes the fd associated with the BigWave instance, the inst (and thusly the job ) is destroyed while bigo_worker_thread continues to reference the job . The highlights indicate any accesses to the UAF’d object: static int bigo_worker_thread ( void * data ) { ... while ( 1 ) { rc = wait_event_timeout ( core -> worker , dequeue_prioq ( core , & job , & should_stop ), msecs_to_jiffies ( BIGO_IDLE_TIMEOUT_MS )); //The job is fetched from the queue ... inst = container_of ( job , struct bigo_inst , job ); //The job is an inline struct inside of the inst which gets UAF'd ... rc = bigo_run_job ( core , job ); ... job -> status = rc ; complete ( & inst -> job_comp ); } return 0 ; } ... static int bigo_run_job ( struct bigo_core *…

Technical Details

Classification
{"confidence":0.3,"severitySource":"default","classifier":"rss-v2"}
Article Source
{"url":"https://projectzero.google/2026/01/pixel-0-click-part-2.html","fetched":true,"fetchedAt":"2026-08-04T12:57:56.509Z","wordCount":2421}

Threat ID: 6a71e1d4bf8831d539d38873

Added to database: 08/04/2026, 12:57:56 UTC

Last updated: 08/04/2026, 12:57:59 UTC

Views: 1

Community Reviews

0 reviews

Crowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.

Sort by
Loading community insights…

Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.

Actions

Please log in to the Console to use AI analysis features.

Need more coverage?

Upgrade to Pro Console for AI refresh and higher limits.

For incident response and remediation, OffSeq services can help resolve threats faster.

Latest Threats

Breach by OffSeqOFFSEQFRIENDS — 25% OFF

Check if your credentials are on the dark web

Instant breach scanning across billions of leaked records. Free tier available.

Scan now
OffSeq TrainingCredly Certified

Lead Pen Test Professional

Technical5-day eLearningPECB Accredited
View courses