Pixel BigWave BIGO timeout race UAF → 2KB kernel write from mediacodec

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

TL;DR

  • From the SELinux-confined mediacodec context, /dev/bigwave (Pixel AV1 hardware accelerator) is reachable. A backlog of jobs makes BIGO_IOCX_PROCESS hit its 16s wait_for_completion_timeout() and return while the worker thread concurrently dequeues the same inline job structure.
  • Closing the FD immediately frees struct bigo_inst (which embeds struct bigo_job). The worker reconstructs inst = container_of(job, ...) and later uses freed fields such as job->regs inside bigo_run_job(), yielding a Use-After-Free on the inline job/inst.
  • bigo_pull_regs(core, job->regs) performs memcpy_fromio(regs, core->base, core->regs_size). By reclaiming the freed slab and overwriting job->regs, an attacker gets a ~2144-byte arbitrary kernel write to a chosen address, with partial control of the bytes by pre-programming register values before the timeout.

Attack surface mapping (SELinux → /dev reachability)

  • Use tools like DriverCartographer to enumerate device nodes accessible from a given SELinux domain. Despite mediacodec’s constrained policy (software decoders should stay in an isolated context), /dev/bigwave remained reachable, exposing a large attack surface to post-media-RCE code.

Vulnerability: BIGO_IOCX_PROCESS timeout vs worker

  • Flow: ioctl copies user register buffer into job->regs, queues the inline job, then wait_for_completion_timeout(..., 16s). On timeout it tries to dequeue/cancel and returns to userspace.
  • Meanwhile bigo_worker_thread may have just dequeued the same job:
inst = container_of(job, struct bigo_inst, job);
bigo_push_regs(core, job->regs);
...
bigo_pull_regs(core, job->regs);   // memcpy_fromio(regs, core->base, core->regs_size)
*(u32 *)(job->regs + BIGO_REG_STAT) = status;
  • Eğer userspace timeout’tan sonra FD’yi kapatırsa, inst/job serbest bırakılırken worker bunları kullanmaya devam eder → UAF. FD ömrünü worker thread’in job işaretçisine bağlayan bir senkronizasyon yok.

İstismar özeti

  1. Backlog + timeout: Worker gecikene kadar yeterli job’u kuyruğa al, sonra BIGO_IOCX_PROCESS çağır ve 16s timeout yoluna girmesine izin ver.
  2. Kullanılırken serbest bırakma: ioctl döner dönmez, worker hala dequeued job’u çalıştırırken inst/job’u serbest bırakmak için close(fd) yap.
  3. Reclaim + pointer control: Boşaltılmış slab slotunu doldurmak ve inline job’u, özellikle job->regs’i ezmek için spray reclaimers (ör. Unix domain socket message allocations) kullan.
  4. Arbitrary write: bigo_pull_regs() çalıştığında, memcpy_fromio() MMIO’dan core->regs_size (~2144 bytes) kadar veriyi job->regs içindeki saldırgan tarafından sağlanan adrese yazar; bu KASLR leak olmadan büyük bir write-what-where üretir.
  5. Veri şekillendirme: Register’lar önce kullanıcı verisinden (bigo_push_regs) programlandığı için, donanımın yürütmemesini sağlayacak şekilde ayarla; böylece kopyalanan register görüntüsü saldırgan kontrollü baytlara yakın kalır.

Sürücü inceleyicileri için çıkarımlar

  • Async worker’lara kuyruğa alınan inline per-FD job struct’ları timeout/iptal yollarından sağ çıkacak referanslar tutmalı; bir FD’nin kapatılması worker tüketimiyle senkronize olmalı.
  • Job’lardan gelen buffer pointer’larını kullanan herhangi bir MMIO copy helper (memcpy_fromio/memcpy_toio) UAF→write primitive’lerini önlemek için kuyruğa alınmadan önce doğrulanmalı veya kopyalanmalı.

References

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin