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

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

TL;DR

  • З контексту SELinux-обмеженого mediacodec доступний /dev/bigwave (апаратний акселератор Pixel AV1). Накопичення завдань призводить до того, що BIGO_IOCX_PROCESS досягає свого 16s wait_for_completion_timeout() і повертає управління, поки потік робітника одночасно dequeues той самий inline job structure.
  • Закриття FD негайно звільняє struct bigo_inst (який містить struct bigo_job). Робітник реконструює inst = container_of(job, ...) і пізніше використовує звільнені поля, такі як job->regs всередині bigo_run_job(), що призводить до Use-After-Free on the inline job/inst.
  • bigo_pull_regs(core, job->regs) виконує memcpy_fromio(regs, core->base, core->regs_size). Після відновлення вільного slab і перезапису job->regs, атакуючий отримує ~2144-byte arbitrary kernel write на вибрану адресу, з частковим контролем байтів шляхом попереднього програмування значень регістрів перед timeout.
  • Ідентифіковано як CVE-2025-36934; виправлено у збірках 2026-01-05 Pixel/2025-12-01 ASB.

Attack surface mapping (SELinux → /dev reachability)

  • Використовуйте інструменти на кшталт DriverCartographer для перерахунку device nodes, доступних з заданого SELinux домену. Незважаючи на обмежену політику mediacodec (software decoders повинні залишатися в ізольованому контексті), /dev/bigwave залишався доступним, відкриваючи велику поверхню атаки для post-media-RCE коду.

Vulnerability: BIGO_IOCX_PROCESS timeout vs worker

  • Потік: ioctl копіює буфер регістрів з користувача в job->regs, ставить inline job у чергу, потім викликається wait_for_completion_timeout(..., 16s). При таймауті воно намагається dequeue/cancel і повертає керування в userspace.
  • Тим часом bigo_worker_thread може щойно dequeued той самий 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;
  • Якщо userspace закриє FD після таймауту, inst/job будуть звільнені, поки worker продовжує їх використовувати → UAF. Немає синхронізації, що прив’язує життєвий цикл FD до вказівника job потоку worker.

Огляд експлуатації

  1. Backlog + timeout: Поставити в чергу достатньо job’ів, щоб worker затримався, потім викликати BIGO_IOCX_PROCESS і дати йому потрапити на шлях таймауту 16s.
  2. Free while in use: Як тільки ioctl повертається, виконати close(fd) щоб звільнити inst/job, поки worker все ще виконує dequeued job.
  3. Reclaim + pointer control: Spray reclaimers (e.g., Unix domain socket message allocations) щоб зайняти звільнений слот slab і перезаписати inline job, особливо job->regs.
  4. Arbitrary write: Коли виконається bigo_pull_regs(), memcpy_fromio() запише core->regs_size (~2144 bytes) з MMIO у адресу, задану атакуючим, в job->regs, створюючи великий write-what-where без KASLR leak.
  5. Data shaping: Оскільки регістри спочатку програмуються з user data (bigo_push_regs), налаштуйте їх так, щоб hardware не виконував код, утримуючи скопійований назад образ регістрів близьким до байтів, контрольованих атакуючим.

Мінімальний PoC скелет (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 повинен попередньо налаштувати BigWave в режим простою (наприклад, встановити біти керування для пропуску виконання), щоб скопійований назад образ регістрів залишався детерміністичним.

Висновки для рецензентів драйверів

  • Inline per-FD job structs, що ставляться в чергу до async workers, мають утримувати посилання, які переживають шляхи timeout/cancel; закриття FD має синхронізуватися зі споживанням worker’а.
  • Будь-які MMIO copy helpers (memcpy_fromio/memcpy_toio), що використовують вказівники на буфери з job-ів, повинні бути перевірені або продубліковані перед постановкою в чергу, щоб уникнути примітивів UAF→write.

Посилання

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks