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

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-confined mediacodec context से, /dev/bigwave (Pixel AV1 hardware accelerator) पहुंच योग्य था। jobs की बैकलॉग के कारण BIGO_IOCX_PROCESS अपना 16s wait_for_completion_timeout() हिट कर देता है और लौट आता है, जबकि worker thread समकक्ष रूप से वही inline job structure dequeue कर रहा होता है।
  • FD बंद करने पर तुरंत struct bigo_inst free हो जाता है (जो struct bigo_job को embed करता है)। worker फिर inst = container_of(job, ...) reconstruct करता है और बाद में freed फ़ील्ड्स जैसे job->regs को bigo_run_job() के अंदर उपयोग करता है, जिससे inline job/inst पर Use-After-Free होता है।
  • bigo_pull_regs(core, job->regs) memcpy_fromio(regs, core->base, core->regs_size) चलाता है। freed slab को reclaim करके और job->regs को overwrite करके, attacker को चुने हुए address पर ~2144-byte arbitrary kernel write मिलता है, जिसमें timeout से पहले register मानों को प्री-प्रोग्राम करके बाईट्स का आंशिक नियंत्रण हासिल किया जा सकता है।
  • ट्रैक किया गया: CVE-2025-36934; फिक्स: 2026-01-05 Pixel/2025-12-01 ASB बिल्ड्स में।

Attack surface mapping (SELinux → /dev reachability)

  • DriverCartographer जैसे टूल का उपयोग करके दिए गए SELinux domain से पहुँचने योग्य device nodes को enumerate करें। mediacodec की constrained policy के बावजूद (software decoders को isolated context में रखा जाना चाहिए), /dev/bigwave पहुँच योग्य रहा, जिससे post-media-RCE कोड के लिए बड़ा attack surface खुल गया।

कमज़ोरी: BIGO_IOCX_PROCESS timeout vs worker

  • प्रवाह: ioctl user register buffer को job->regs में copy करता है, inline job queue करता है, फिर wait_for_completion_timeout(..., 16s) कॉल होता है। timeout पर यह dequeue/cancel करने की कोशिश करता है और userspace को लौटता है।
  • इस बीच 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। कोई synchronization FD के lifetime को worker thread के job pointer से नहीं जोड़ती।

शोषण रूपरेखा

  1. Backlog + timeout: पर्याप्त jobs को queue करें ताकि worker देरी हो, फिर BIGO_IOCX_PROCESS जारी करें और इसे 16s timeout path तक पहुँचने दें।
  2. Free while in use: जैसे ही ioctl लौटता है, close(fd) करके inst/job को तब तक फ्री कर दें जबकि worker अभी भी dequeued job चला रहा हो।
  3. Reclaim + pointer control: फ्री किए गए slab slot को भरने और inline job को overwrite करने के लिए reclaimers स्प्रे करें (उदा., Unix domain socket message allocations), खासकर job->regs
  4. Arbitrary write: जब bigo_pull_regs() चलता है, memcpy_fromio() MMIO से core->regs_size (~2144 bytes) को attacker-supplied address में job->regs पर लिखता है, जिससे KASLR leak के बिना एक बड़ा write-what-where बनता है।
  5. Data shaping: क्योंकि registers पहले user डेटा (bigo_push_regs) से प्रोग्राम किए जाते हैं, उन्हें इस तरह सेट करें कि hardware execute न करे, ताकि copied-back register image attacker-controlled बाइट्स के करीब रहे।

न्यूनतम 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 को BigWave को निष्क्रिय करने के लिए पूर्व-संरचित किया जाना चाहिए (उदा., execution छोड़ने के लिए control bits सेट करें) ताकि कॉपी-बैक किया गया रजिस्टर इमेज निश्चित रहे।

ड्राइवर समीक्षकों के लिए निष्कर्ष

  • Inline per-FD job structs जो async workers में enqueue किए गए हैं, उन्हें ऐसे references होने चाहिए जो timeout/cancel paths से गुजरने पर भी कायम रहें; FD को बंद करना worker की consumption के साथ समन्वयित होना चाहिए
  • Any MMIO copy helpers (memcpy_fromio/memcpy_toio) जो jobs से buffer pointers का उपयोग करते हैं, उन्हें enqueue करने से पहले सत्यापित या डुप्लिकेट किया जाना चाहिए ताकि 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 का समर्थन करें