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

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

TL;DR

  • Aus dem SELinux-eingeschränkten mediacodec-Kontext ist /dev/bigwave (Pixel AV1 hardware accelerator) erreichbar. Ein Rückstau von Jobs lässt BIGO_IOCX_PROCESS seine 16s wait_for_completion_timeout() erreichen und zurückkehren, während der Worker-Thread gleichzeitig dieselbe inline-job-Struktur dequeues.
  • Das Schließen des FD gibt sofort struct bigo_inst frei (die struct bigo_job einbettet). Der Worker rekonstruiert inst = container_of(job, ...) und verwendet später freigegebene Felder wie job->regs innerhalb von bigo_run_job(), was zu einem Use-After-Free on the inline job/inst führt.
  • bigo_pull_regs(core, job->regs) führt memcpy_fromio(regs, core->base, core->regs_size) aus. Durch Zurückgewinnen des freigegebenen Slabs und Überschreiben von job->regs erhält ein Angreifer einen ~2144-byte arbitrary kernel write an eine gewählte Adresse, mit teilweiser Kontrolle über die Bytes durch Vorausprogrammierung der Registerwerte vor dem Timeout.
  • Erfasst als CVE-2025-36934; behoben in den Builds 2026-01-05 Pixel/2025-12-01 ASB.

Attack surface mapping (SELinux → /dev reachability)

  • Verwende Tools wie DriverCartographer, um device nodes aufzulisten, die von einer bestimmten SELinux-Domain erreichbar sind. Trotz der eingeschränkten mediacodec-Policy (software decoders sollten in einem isolierten Kontext bleiben) blieb /dev/bigwave erreichbar und stellte eine große Angriffsfläche gegenüber post-media-RCE-Code dar.

Vulnerability: BIGO_IOCX_PROCESS timeout vs worker

  • Ablauf: ioctl kopiert den User-Register-Buffer in job->regs, queue’t die inline-job-Struktur, dann wird wait_for_completion_timeout(..., 16s) aufgerufen. Bei Timeout versucht es, das job zu dequeue/cancel und kehrt in den Userspace zurück.
  • Unterdessen könnte bigo_worker_thread soeben dasselbe job dequeued haben:
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;
  • Wenn userspace den FD nach dem Timeout schließt, werden inst/job freigegeben, während der worker sie weiterhin benutzt → UAF. Es gibt keine Synchronisation, die die Lebensdauer des FD an den job-Pointer des worker-Threads bindet.

Ausnutzungsübersicht

  1. Backlog + timeout: Queue genug Jobs, sodass der worker verzögert wird, dann BIGO_IOCX_PROCESS ausführen und den 16s-Timeout-Pfad erreichen.
  2. Free while in use: Sobald ioctl zurückkehrt, close(fd) ausführen, um inst/job freizugeben, während der worker noch den aus der Queue entnommenen Job ausführt.
  3. Reclaim + pointer control: Spray reclaimers (z. B. Unix domain socket message-Allokationen), um den freigegebenen Slab-Slot zu belegen und das inline-job zu überschreiben, insbesondere job->regs.
  4. Arbitrary write: Wenn bigo_pull_regs() ausgeführt wird, schreibt memcpy_fromio() core->regs_size (~2144 bytes) von MMIO in die vom Angreifer angegebene Adresse in job->regs, wodurch ein großer write-what-where ohne KASLR leak entsteht.
  5. Data shaping: Da Register zuerst aus Benutzerdaten (bigo_push_regs) programmiert werden, setze sie so, dass die Hardware nicht ausführt, wodurch das zurückkopierte Registerbild nahe an vom Angreifer kontrollierten Bytes bleibt.

Minimaler 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 sollte BigWave so vorkonfigurieren, dass es inaktiv ist (z. B. Steuerbits setzen, um die Ausführung zu überspringen), damit das zurückkopierte Registerabbild deterministisch bleibt.

Erkenntnisse für Treiberprüfer

  • Inline pro-FD job structs, die in async workers eingereiht werden, müssen Referenzen halten, die Timeout-/Cancel-Pfade überstehen; das Schließen einer FD muss mit dem Verbrauch durch den Worker synchronisiert werden.
  • Alle MMIO copy helpers (memcpy_fromio/memcpy_toio), die Buffer-Pointer aus Jobs verwenden, sollten validiert oder dupliziert werden, bevor sie enqueued werden, um UAF→write primitives zu vermeiden.

References

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks