Pixel BigWave BIGO timeout race UAF → mediacodec에서 2KB 커널 쓰기

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

TL;DR

  • SELinux로 제한된 mediacodec 컨텍스트에서 /dev/bigwave(Pixel AV1 hardware accelerator)에 접근할 수 있습니다. 작업이 쌓이면 BIGO_IOCX_PROCESS가 **16s wait_for_completion_timeout()**에 걸려 반환되는 동안 워커 스레드가 동일한 inline job 구조를 동시에 dequeue할 수 있습니다.
  • FD를 즉시 닫으면 struct bigo_inst(내부에 struct bigo_job을 포함)가 해제됩니다. 워커는 inst = container_of(job, ...)을 재구성하고 이후 bigo_run_job() 내부에서 job->regs 같은 해제된 필드를 사용하여 inline job/inst에 대한 Use-After-Free를 유발합니다.
  • bigo_pull_regs(core, job->regs)memcpy_fromio(regs, core->base, core->regs_size)를 수행합니다. 해제된 slab를 재할당하고 job->regs를 덮어쓰면, 공격자는 타깃 주소에 대해 약 2144바이트 임의의 커널 쓰기를 얻을 수 있으며, 타임아웃 전에 레지스터 값을 미리 설정해 바이트의 일부를 제어할 수 있습니다.
  • 이 취약점은 CVE-2025-36934로 추적되며; 2026-01-05 Pixel / 2025-12-01 ASB 빌드에서 수정되었습니다.

Attack surface mapping (SELinux → /dev reachability)

  • DriverCartographer와 같은 도구를 사용해 특정 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/취소를 시도하고 유저스페이스로 반환합니다.
  • 그 사이에 bigo_worker_thread는 동일한 job을 방금 dequeue했을 수 있습니다:
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가 timeout 이후 FD를 닫으면, inst/job는 worker가 계속 사용하는 동안 해제되어 → UAF가 발생합니다. FD 수명과 worker 스레드의 job 포인터를 묶는 동기화가 없습니다.

익스플로잇 개요

  1. 대기열 + 타임아웃: worker가 지연되도록 충분한 job을 큐에 넣은 뒤, BIGO_IOCX_PROCESS를 발행하고 16s 타임아웃 경로에 도달하게 합니다.
  2. 사용 중에 해제: ioctl이 반환되자마자 close(fd)로 worker가 아직 실행 중인 디큐된 job의 inst/job를 해제합니다.
  3. 재할당 + 포인터 제어: 반환된 slab 슬롯을 차지하도록 reclaimers(예: Unix domain socket message 할당)를 스프레이해서 inline job—특히 job->regs—를 덮어씁니다.
  4. 임의 쓰기: bigo_pull_regs()가 실행되면 memcpy_fromio()가 MMIO로부터 **core->regs_size (~2144 bytes)**만큼을 공격자가 제공한 주소인 job->regs로 써서, KASLR leak 없이 대규모의 write-what-where를 만듭니다.
  5. 데이터 조형: 레지스터가 먼저 사용자 데이터(bigo_push_regs)로부터 설정되기 때문에, 하드웨어가 실행하지 않도록 레지스터 값을 설정해 복사된 레지스터 이미지가 공격자가 제어하는 바이트에 가깝게 유지되도록 합니다.

최소 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를 idle 상태로 미리 구성해야 합니다(예: 실행을 건너뛰도록 제어 비트 설정).

드라이버 리뷰어를 위한 요점

  • async workers에 enqueued된 inline per-FD job struct는 timeout/취소 경로에서도 유효한 참조를 유지해야 합니다; FD를 닫는 동작은 worker의 소비와 동기화되어야 합니다.
  • jobs에서 온 버퍼 포인터를 사용하는 모든 MMIO 복사 헬퍼(memcpy_fromio/memcpy_toio)는 enqueuing 전에 검증하거나 복제해야 UAF→write primitives를 방지할 수 있습니다.

참고자료

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기