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

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

TL;DR

  • Desde el contexto SELinux confinado mediacodec, /dev/bigwave (Pixel AV1 hardware accelerator) es accesible. Una acumulación de jobs hace que BIGO_IOCX_PROCESS alcance su 16s wait_for_completion_timeout() y retorne mientras el hilo worker simultáneamente hace dequeue de la misma estructura inline job.
  • Cerrar el FD libera inmediatamente struct bigo_inst (que embebe struct bigo_job). El worker reconstruye inst = container_of(job, ...) y luego usa campos ya liberados como job->regs dentro de bigo_run_job(), provocando un Use-After-Free on the inline job/inst.
  • bigo_pull_regs(core, job->regs) realiza memcpy_fromio(regs, core->base, core->regs_size). Al reclamar el slab liberado y sobrescribir job->regs, un atacante obtiene un ~2144-byte arbitrary kernel write a una dirección elegida, con control parcial de los bytes preprogramando valores de registro antes del timeout.
  • Rastreado como CVE-2025-36934; corregido en las builds 2026-01-05 Pixel/2025-12-01 ASB.

Attack surface mapping (SELinux → /dev reachability)

  • Usa herramientas como DriverCartographer para enumerar nodos de dispositivo accesibles desde un dominio SELinux dado. A pesar de la política restringida de mediacodec (los decoders por software deben permanecer en un contexto aislado), /dev/bigwave siguió siendo accesible, exponiendo una gran superficie de ataque al código post-media-RCE.

Vulnerability: BIGO_IOCX_PROCESS timeout vs worker

  • Flow: ioctl copia el buffer de registros de usuario en job->regs, encola el job inline, luego se llama a wait_for_completion_timeout(..., 16s). En el timeout intenta hacer dequeue/cancel y retorna a userspace.
  • Mientras tanto bigo_worker_thread puede haber justo hecho dequeue del mismo 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;
  • Si userspace cierra el FD después del timeout, inst/job se liberan mientras el worker sigue usándolos → UAF. No hay sincronización que vincule la vida del FD con el puntero job del worker thread.

Exploitation outline

  1. Backlog + timeout: Encola suficientes jobs para retrasar al worker, luego ejecuta BIGO_IOCX_PROCESS y deja que alcance la ruta de timeout de 16s.
  2. Free while in use: Tan pronto como ioctl retorna, llama a close(fd) para liberar inst/job mientras el worker todavía está ejecutando el job desencolado.
  3. Reclaim + pointer control: Spray reclaimers (p. ej., Unix domain socket message allocations) para ocupar la ranura de slab liberada y sobrescribir el job inline, especialmente job->regs.
  4. Arbitrary write: Cuando bigo_pull_regs() se ejecuta, memcpy_fromio() escribe core->regs_size (~2144 bytes) desde MMIO hacia la dirección provista por el atacante en job->regs, produciendo una gran write-what-where sin un KASLR leak.
  5. Data shaping: Dado que los registros primero se programan desde datos de usuario (bigo_push_regs), configúralos para que el hardware no ejecute, manteniendo la imagen de registros copiada cerca de bytes controlados por el atacante.

Minimal PoC skeleton (blocking backlog + reclaim)

int fd = open("/dev/bigwave", O_RDWR);
for (int i = 0; i < 64; i++) submit_job(fd, regs_buf);   // fill worker queue
submit_job(fd, regs_buf);                                // victim job
auto t0 = now();
while (now() - t0 < 17000ms) sched_yield();              // hit 16s timeout
close(fd);                                               // free inst/job
spray_uds_msgs(payload_pointing_to_target, spray_count); // reclaim slab
sleep(1);                                                // let worker memcpy_fromio
  • regs_buf debería preconfigurar BigWave para que esté idle (p. ej., establecer bits de control para omitir la ejecución) de modo que la imagen de registros copiada de vuelta permanezca determinista.

Takeaways for driver reviewers

  • Las estructuras de job por-FD inline encoladas a async workers deben mantener referencias que sobrevivan a las rutas de timeout/cancelación; cerrar un FD debe sincronizarse con el consumo por el worker.
  • Cualquier helper de copia MMIO (memcpy_fromio/memcpy_toio) que use punteros de buffer provenientes de jobs debe validarse o duplicarse antes de encolar para evitar primitivas UAF→write.

References

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks