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-सीमित mediacodec context से, /dev/bigwave (Pixel AV1 hardware accelerator) पहुँचा जा सकता है। नौकरियों के बैकलॉग के कारण BIGO_IOCX_PROCESS इसका 16s wait_for_completion_timeout() हिट कर वापिस लौटता है जबकि worker thread समानांतर में उसी inline job संरचना को dequeue कर देता है।
  • FD को तुरंत बंद करने से struct bigo_inst (जो struct bigo_job को embed करता है) free हो जाता है। worker inst = container_of(job, ...) पुनर्निर्माण करता है और बाद में 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 को फिर से हासिल करके और job->regs को overwrite करके, attacker को किसी चुने हुए पते पर ~2144-byte arbitrary kernel write मिल जाता है, और timeout से पहले register values प्री-प्रोग्राम करके उस लिखे हुए बाइट्स पर आंशिक नियंत्रण हासिल किया जा सकता है।

Attack surface mapping (SELinux → /dev पहुँचयोग्यता)

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

Vulnerability: BIGO_IOCX_PROCESS timeout vs worker

  • Flow: 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 को close कर देता है, तो inst/job free हो जाते हैं जबकि worker उन्हें उपयोग करता रहता है → UAF. FD की lifetime को worker thread के job pointer के साथ कोई सिंक्रोनाइज़ेशन जुड़ा नहीं है।

Exploitation outline

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

Takeaways for driver reviewers

  • Inline per-FD job structs जो async workers को enqueue होते हैं, उन्हें ऐसे references रखने चाहिए जो timeout/cancel पथों में भी जीवित रहें; FD close होना worker consumption के साथ synchronize होना चाहिए
  • कोई भी MMIO copy helper (memcpy_fromio/memcpy_toio) जो jobs से buffer pointers उपयोग करता है, उन्हें enqueue करने से पहले validate या duplicate किया जाना चाहिए ताकि UAF→write primitives न बनें।

References

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 का समर्थन करें