
# CVE-2025-8045 के लिए डर्टी पेजटेबल एक्सप्लॉइट
CVE-2025-8045 के लिए एक लोकल प्रिविलेज एस्केलेशन एक्सप्लॉइट, जो Arm Mali GPU कर्नेल ड्राइवर (kbase) में एक use-after-free दोष है। एक गैर-विशेषाधिकार प्राप्त स्थानीय प्रक्रिया CSF KCPU queue डंप पथ को race करके cpu_queue.buffer को मुक्त कर पुनः प्राप्त करती है, लटकते आवंटन को अपनी स्वामित्व वाली पेज टेबल ("dirty pagetable") में बदल देती है, और उस प्रिमिटिव का उपयोग करके कर्नेल की आर्बिट्ररी भौतिक रीड/राइट प्राप्त करती है — अंततः SELinux को permissive किए हुए रूट शेल तक पहुँचती है।
Pixel 7 Pro पर शोषित (build
BP3A.250905.014)।exploit.cमें हार्डकोडेड ऑफ़सेट इसी लक्ष्य के लिए अंशांकित हैं; अन्य डिवाइसों/बिल्डों के लिए ऑफ़सेट पुनः व्युत्पन्न करने होंगे (देखें ट्यूनिंग और पोर्टेबिलिटी)।
CVE-2025-8045, Arm Valhall और 5वीं पीढ़ी GPU आर्किटेक्चर कर्नेल ड्राइवरों (r53p0–r54p1) में एक use-after-free दोष है। एक स्थानीय, गैर-विशेषाधिकार प्राप्त प्रक्रिया GPU प्रोसेसिंग ऑपरेशनों को इस प्रकार चला सकती है कि ड्राइवर पहले से मुक्त की गई मेमोरी पर कार्य करता रहे, जिससे कर्नेल मेमोरी डिस्क्लोज़र, भ्रष्टाचार और कोड निष्पादन का मार्ग खुलता है।
यह एक्सप्लॉइट /dev/mali0 द्वारा उजागर CSF KCPU queue इंटरफ़ेस के माध्यम से इस दोष तक पहुँचता है:
CQS_WAIT के साथ सशस्त्र किया जाता है और उसके बाद FENCE_SIGNAL होता है। यह प्रतीक्षा queue को रोक देती है, जिससे फेंस टाइमर बाद में, टाइमर-व्हील बकेट की पूर्वानुमेय सीमा पर ट्रिगर होता है।KBASE_IOCTL_CS_CPU_QUEUE_DUMP, kbase_csf_cpu_queue_dump_buffer() को संचालित करता है। Queue की स्थिति संक्रमण (ISSUED → COMPLETE/PENDING) को डंप पथ के विरुद्ध race करने पर cpu_queue.buffer उस समय मुक्त हो जाता है जब वह अभी भी संदर्भित है — यही UAF है।यह एक्सप्लॉइट एक टाइमिंग एक्सप्लॉइट है: यह पहले डेडलाइन को कैलिब्रेट करता है, फिर प्रत्येक राउंड में उसका पूर्वानुमान लगाता है और मुक्ति के क्षण के आसपास race विंडो को चौड़ा करने हेतु हानिरहित डंप कॉलों की एक "लहर" दागता है।
चूँकि एक पेज अंततः एक साथ Mali आवंटन और एक सक्रिय CPU पेज टेबल बन जाता है, प्रक्रिया बाहर निकलने के बजाय हमेशा के लिए पार्क रहती है — इसे मुक्त करना double-free होगा और कर्नेल पैनिक कर देगा।
# Android / arm64 (NDK)
aarch64-linux-android31-clang -O2 -o exploit exploit.c
./exploit
सफलता पर आपको SELinux permissive के साथ रूट शेल (uid=0) मिलती है। नमूना प्रवाह:
[*] pid=... cpus=8 wave=64 harvest cpu=7 rounds=256
[*] round 1 calibrate deadline t0+... ms phase ... ms
[*] round N read +... us
[+] UAF page: spray region R page P @ ..., 1 live descriptor
[+] entry 0 = ... -- a CPU page table, writable through the GPU
[+] alias: dirty pagetable
[+] selinux_state.enforcing = 0 @ phys ...
[+] sel_read_enforce patched @ phys ...
[+] root shell: uid=0 euid=0
यदि यह बिना सफलता के सभी राउंड चला लेता है, तो dmesg में cpu_queue.c:71 संकेत देता है कि race सही जगह लग रही है किंतु रीक्लेम चूक गया — रीक्लेम/वेव पैरामीटरों को ट्यून करें।
exploit.c में मान Pixel 7 Pro, build BP3A.250905.014 के लिए अंशांकित हैं। ऑफ़सेट और स्थिरांक डिवाइस/कर्नेल-विशिष्ट हैं और किसी अन्य लक्ष्य के लिए पुनः व्युत्पन्न किए जाने चाहिए:
KERNEL_PA_BASE, SEL_READ_ENFORCE, INIT_CRED, COMMIT_CREDS, SELINUX_STATE — कर्नेल सिंबल/भौतिक ऑफ़सेट।ARM64_PTE_FLAGS — लक्ष्य MMU कॉन्फ़िगरेशन के लिए अंतिम-स्तर डिस्क्रिप्टर टेम्पलेट।WAVE_*, SWEEP_*, BUCKET_NS, WAIT_NS, स्प्रे आकार — race टाइमिंग और हीप-ग्रूमिंग नॉब्स।उपचार के लिए Arm से जारी सुधारित ड्राइवर रिलीज़ में अपडेट करें।
यह कोड केवल रक्षात्मक सुरक्षा अनुसंधान, डिटेक्शन इंजीनियरिंग और शिक्षा हेतु प्रकाशित किया गया है। इसे उन प्रणालियों पर न चलाएँ जिनके स्वामी आप नहीं हैं या जिनके परीक्षण हेतु आपके पास स्पष्ट लिखित प्राधिकरण नहीं है। लेखक दुरुपयोग या उत्पन्न किसी भी क्षति के लिए कोई दायित्व स्वीकार नहीं करता है। अनुमति के बिना प्रणालियों के विरुद्ध इसका उपयोग अवैध है।
| चरण | क्या होता है |
|---|
| कैलिब्रेट | राउंड 1, ISSUED→COMPLETE किनारे को मापता है ताकि टाइमर-व्हील बकेट फेज़ का पता चले। |
| पूर्वानुमान + स्वीप | बाद के राउंड डेडलाइन का पूर्वानुमान लगाते हैं और रीड ऑफ़सेट को ±ms स्वीप करते हैं ताकि ठीक मुक्ति पर पहुँचा जा सके। |
| वेव | 64 थ्रेड्स डेडलाइन को घेरने और विंडो को खींचने के लिए CS_CPU_QUEUE_DUMP कॉलों को csf.lock पर ढेर कर देते हैं। |
| रीक्लेम | UNMOVABLE फ्री लिस्टों को पहले से खाली करें, फिर स्टैम्प्ड GPU पेजों को स्प्रे करें ताकि मुक्त ब्लॉक हमारे नियंत्रण में वापस आ जाए। |
| डर्टी पेजटेबल | पुनः मुक्त करें और तुरंत उसी पेज में CPU पेज टेबलों को स्प्रे करें; अब GPU आवंटन एक सक्रिय अंतिम-स्तर तालिका के साथ अलियास करता है। |
| आर्बिट्ररी R/W | एक कभी-पुनः-उपयोग न किया गया window PTE कर्नेल भौतिक पेजों की ओर इंगित किया जाता है; एक बड़ी स्क्रैच मैपिंग पर PROT_NONE राउंड-ट्रिप के माध्यम से TLB को बलपूर्वक फ्लश किया जाता है। |
| रूट | selinux_state.enforcing को साफ़ करें, sel_read_enforce को commit_creds(init_cred) से पैच करें, एक पार्क्ड चाइल्ड को छोड़ें जो रूट शेल चलाता है। |