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

Tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

TL;DR

  • Z kontekstu SELinux ograniczonego mediacodec, /dev/bigwave (Pixel AV1 hardware accelerator) jest osiągalny. Nagromadzenie zadań powoduje, że BIGO_IOCX_PROCESS trafia na swoje 16s wait_for_completion_timeout() i zwraca kontrolę, podczas gdy wątek roboczy równocześnie dequeues ten sam inline job (strukturę).
  • Zamknięcie FD natychmiast zwalnia struct bigo_inst (która osadza struct bigo_job). Wątek roboczy rekonstruuje inst = container_of(job, ...) i później używa zwolnionych pól takich jak job->regs wewnątrz bigo_run_job(), prowadząc do Use-After-Free on the inline job/inst.
  • bigo_pull_regs(core, job->regs) wykonuje memcpy_fromio(regs, core->base, core->regs_size). Poprzez odzyskanie zwolnionego slab i nadpisanie job->regs, atakujący uzyskuje ~2144-byte arbitrary kernel write pod wybrany adres, z częściową kontrolą nad bajtami przez uprzednie zaprogramowanie wartości rejestrów przed timeoutem.

Attack surface mapping (SELinux → /dev reachability)

  • Użyj narzędzi takich jak DriverCartographer do enumeracji device nodes dostępnych z danego domeny SELinux. Pomimo ograniczonej polityki mediacodec (software decoders powinny pozostać w izolowanym kontekście), /dev/bigwave pozostał osiągalny, wystawiając dużą powierzchnię ataku na kod działający po media-RCE.

Vulnerability: BIGO_IOCX_PROCESS timeout vs worker

  • Flow: ioctl kopiuje user register buffer do job->regs, enqueueuje inline job, a następnie wywołuje wait_for_completion_timeout(..., 16s). Po upływie czasu próbuje dequeue/cancel i zwraca kontrolę do userspace.
  • Tymczasem bigo_worker_thread mógł właśnie dequeued ten sam 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;
  • If userspace closes the FD after the timeout, inst/job are freed while the worker keeps using them → UAF. No synchronization ties FD lifetime to the worker thread’s job pointer.

Zarys eksploatacji

  1. Backlog + timeout: Wstaw wystarczająco dużo job do kolejki, by worker został opóźniony, następnie wywołaj BIGO_IOCX_PROCESS i pozwól, by trafił na ścieżkę 16s timeout.
  2. Free while in use: Gdy tylko ioctl zwróci, wykonaj close(fd), aby zwolnić inst/job, podczas gdy worker nadal wykonuje wyjęty z kolejki job.
  3. Reclaim + pointer control: Spray reclaimers (np. Unix domain socket message allocations) aby zająć zwolniony slot slab i nadpisać inline job, w szczególności job->regs.
  4. Arbitrary write: Gdy bigo_pull_regs() zostanie wykonane, memcpy_fromio() zapisuje core->regs_size (~2144 bytes) z MMIO do adresu w job->regs podanego przez atakującego, generując duży write-what-where without a KASLR leak.
  5. Data shaping: Ponieważ rejestry są najpierw programowane z danych użytkownika (bigo_push_regs), ustaw je tak, aby hardware nie wykonywał kodu, utrzymując skopiowany obraz rejestrów blisko bajtów kontrolowanych przez atakującego.

Wnioski dla recenzentów sterownika

  • Inline per-FD job structs enqueued to async workers must hold references that survive timeout/cancel paths; closing an FD must synchronize with worker consumption.
  • Wszelkie MMIO copy helpers (memcpy_fromio/memcpy_toio) które używają wskaźników bufora z job powinny być walidowane lub zdublowane przed enqueuing, aby uniknąć UAF→write prymitywów.

Referencje

Tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks