
CVE-2026-43655 AppleM2ScalerCSCDriver use-after-free के लिए सार्वजनिक प्रकटीकरण
CVE-2026-43655 के लिए सार्वजनिक तकनीकी प्रकटीकरण, एक AppleM2ScalerCSCDriver / IOSurfaceAccelerator यूज़-आफ्टर-फ्री (use-after-free) जो डिफ़ॉल्ट iOS ऐप सैंडबॉक्स से बिना किसी विशेष अधिकार (entitlements) के पहुँच योग्य है।
Apple ने इस समस्या को iOS 26.5 / iPadOS 26.5 / macOS Tahoe 26.5 में ठीक किया। इस रिपॉजिटरी में ऑब्जेक्टिव-सी (Objective-C) प्रूफ-ऑफ-कॉन्सेप्ट (PoC) सोर्स, न्यूनतम अधिकार (entitlements), एक बिल्ट IPA, और तकनीकी व्याख्या शामिल है, जो समस्या को समझने और किसी प्रभावित डिवाइस पर पुन: उत्पन्न करने के लिए आवश्यक है।
बग स्केलर शेड्यूलर (scaler scheduler) में एक टियरडाउन/लाइफ़टाइम (teardown/lifetime) त्रुटि है। एक उपयोगकर्ता प्रक्रिया (user process) एसिंक्रोनस स्केलर ऑपरेशन सबमिट कर सकती है, उन ऑपरेशनों के मालिक IOSurfaceAcceleratorClient कनेक्शन को बंद कर सकती है, और एक ड्राइवर-ग्लोबल शेड्यूलर संरचना में पुरानी प्रविष्टियाँ (stale entries) छोड़ सकती है। बाद में शेड्यूलर पास उन प्रविष्टियों को प्रोसेस कर सकता है जो अब मुक्त और पुन: उपयोग की गई ऑपरेशन स्टोरेज की ओर इशारा करती हैं।
PoC दो अलग-अलग मार्कर मानों (marker values) के साथ लाइफ़टाइम बग प्रदर्शित करता है:
0xDEAD00010xBEEF0002विक्टिम कनेक्शन एसिंक्रोनस ऑपरेशन सबमिट करता है और फिर बंद कर दिया जाता है। उसके बाद रिप्लेसमेंट कनेक्शन खोले जाते हैं और अपना मार्कर 0xBEEF0002 सेट करते हैं। जब अगला स्केलर शेड्यूलिंग चक्र चलता है, तो गलती (fault) रिप्लेसमेंट मार्कर (x9 = 0x00000000BEEF0002) देखती है, विक्टिम मार्कर नहीं। यह साबित करता है कि शेड्यूलर ने एक ऑपरेशन स्लॉट से पढ़ा जो मुक्त हो चुका था और फिर एक अलग कनेक्शन को पुन: आवंटित (reallocated) कर दिया गया था।
com.apple.driver.AppleM2ScalerCSCDriverIOSurfaceAcceleratorClientget-task-allowAppleM2ScalerCSCDriver स्केलर क्लाइंट के बीच शेड्यूलर स्थिति (scheduler state) साझा रखता है। प्रासंगिक लाइफ़टाइम बेमेल (lifetime mismatch) इस प्रकार है:
IOServiceClose के साथ बंद कर दिया जाता है।टियरडाउन पथ बंद होने वाले क्लाइंट की लंबित शेड्यूलर प्रविष्टियों को साझा शेड्यूलर हीप (shared scheduler heap) से नहीं हटाता है। शेड्यूलर बाद में उन पुराने पॉइंटर्स के माध्यम से फ़ील्ड पढ़ता और लिखता है।
विश्लेषण के दौरान देखे गए महत्वपूर्ण फ़ील्ड:
| ऑफ़सेट (Offset) | शेड्यूलर व्यवहार (Scheduler behavior) |
|---|---|
operation + 0xc94 | क्रेडिट/मार्कर मान के रूप में पढ़ा जाता है, जिसका उपयोग क्रेडिट-रिज़ॉल्यूशन पथ (credit-resolution path) द्वारा किया जाता है |
operation + 0xc1c | शेड्यूलर क्रेडिट अकाउंटिंग पथ द्वारा लिखा जाता है |
operation + 0x1fe4 | शेड्यूलर स्थिति/फ़्लैग अपडेट पथ द्वारा लिखा जाता है |
ऑपरेशन आवंटक (operation allocator) का व्यवहार बग को देखने योग्य बनाता है: मुक्त ऑपरेशन स्लॉट बाद में विभिन्न कनेक्शनों से ऑपरेशन द्वारा पुन: उपयोग किए जा सकते हैं। एक विक्टिम कनेक्शन को बंद करके और तुरंत नए कनेक्शन स्प्रे करके, PoC पुराने शेड्यूलर प्रविष्टियों को उस मेमोरी की ओर इशारा करने का कारण बन सकता है जो अब स्प्रे कनेक्शनों के स्वामित्व में है।
x9 = 0xBEEF0002 UAF को क्यों साबित करता हैPoC विक्टिम/स्प्रे विभाजन का उपयोग करता है:
0xDEAD0001 सेट करता है।0xBEEF0002 सेट करते हैं।यदि शेड्यूलर अभी भी जीवित विक्टिम-स्वामित्व वाले ऑब्जेक्ट पढ़ रहा होता, तो देखा गया मान 0xDEAD0001 होता। इसके बजाय, पुन: उत्पन्न गलती 0xBEEF0002 देखती है, जो प्रतिस्थापन स्प्रे कनेक्शनों द्वारा लिखा गया मान है। यह मुख्य प्रमाण है कि शेड्यूलर एक पुराने पॉइंटर को मुक्त और पुन: उपयोग की गई कर्नेल मेमोरी में डीरेफरेंस कर रहा है।
यह क्रॉस-कनेक्शन प्रभाव (cross-connection impact) भी दिखाता है: शेड्यूलर प्रविष्टि एक कनेक्शन द्वारा बनाई गई थी, लेकिन बाद में जो मेमोरी उसने छुआ वह दूसरे कनेक्शन के लिए पुनर्चक्रित (recycled) हो चुकी थी। पुन: उत्पन्न रनों में, अंतिम शेड्यूलर गतिविधि मूल PoC प्रक्रिया के बजाय सामान्य SpringBoard/कम्पोज़िटर/UI गतिविधि द्वारा संचालित हो सकती है।
सार्वजनिक Apple सलाहकार (advisory) प्रभाव का वर्णन इस प्रकार करता है: “एक ऐप अप्रत्याशित सिस्टम समाप्ति का कारण बन सकता है या कर्नेल मेमोरी पढ़ सकता है।”
महत्वपूर्ण पुनरुत्पादन विवरण: TEARDOWN UAF टैप करने के बाद, डिवाइस तुरंत पैनिक (panic) नहीं करता है। PoC पहले पुरानी शेड्यूलर स्थिति तैयार करता है। बग अगले स्केलर शेड्यूलिंग चक्र पर ट्रिगर होता है, जो व्यवहार में तब होता है जब SpringBoard/कम्पोज़िटर गतिविधि स्केलर को चलाती है। मेरे भौतिक-डिवाइस पुनरुत्पादन में, मैंने PoC द्वारा पुरानी शेड्यूलर स्थिति तैयार करने के बाद डायनामिक आइलैंड (Dynamic Island) पर टैप/इंटरैक्ट करके उस शेड्यूलर चक्र को ट्रिगर किया।
चरण:
ScalerTeardownUAF.ipa इंस्टॉल और लॉन्च करें।AppleM2ScalerCSCDriver कनेक्शन खोलता है।IOSurface ऑब्जेक्ट बनाता है।0xDEAD0001 पर सेट करता है।IOServiceClose के साथ बंद करता है, जिससे विक्टिम-स्वामित्व वाले ऑपरेशन ऑब्जेक्ट मुक्त हो जाते हैं जबकि पुरानी शेड्यूलर प्रविष्टियाँ बनी रहती हैं।0xBEEF0002 पर सेट करता है।x9 = 0x00000000BEEF0002 होना सत्यापित करें।अपेक्षित प्रमाण शर्त:
x9 = 0x00000000BEEF0002 का अर्थ है कि शेड्यूलर ने स्प्रे मार्कर को उस मेमोरी से पढ़ा जो मूल रूप से मुक्त विक्टिम ऑपरेशन की थी।0xBEEF0002 विक्टिम मार्कर नहीं है; यह प्रतिस्थापन कनेक्शन मार्कर है।शामिल सोर्स निम्नलिखित अनुक्रम निष्पादित करता है:
विक्टिम कनेक्शन खोलें
IOSurface स्रोत/गंतव्य जोड़ी बनाएं
सिंक बेसलाइन स्केलर अनुरोध सबमिट करें
विक्टिम मार्कर = 0xDEAD0001 सेलेक्टर 10 के माध्यम से सेट करें
50 एसिंक्रोनस स्केलर ऑपरेशन सबमिट करें
विक्टिम कनेक्शन बंद करें
50 स्प्रे कनेक्शन खोलें
स्प्रे मार्कर = 0xBEEF0002 सेलेक्टर 10 के माध्यम से सेट करें
स्प्रे कनेक्शनों पर बार-बार एसिंक्रोनस स्केलर ऑपरेशन सबमिट करें
SpringBoard/कम्पोज़िटर शेड्यूलर ट्रिगर की प्रतीक्षा करें
प्रासंगिक सोर्स फ़ाइल है ScalerTeardownUAF.m।
xcrun -sdk iphoneos clang -framework Foundation -framework UIKit -framework IOKit \
-framework IOSurface -isysroot $(xcrun --sdk iphoneos --show-sdk-path) \
-arch arm64 -arch arm64e -miphoneos-version-min=16.0 -fobjc-arc \
-o iPhoneProbe.app/iPhoneProbe ScalerTeardownUAF.m
ldid -S entitlements.plist iPhoneProbe.app/iPhoneProbe
mkdir -p /tmp/pkg/Payload
cp -r iPhoneProbe.app /tmp/pkg/Payload/
cd /tmp/pkg && zip -qr ScalerTeardownUAF.ipa Payload
| फ़ाइल | विवरण |
|---|---|
ScalerTeardownUAF.m | ऑब्जेक्टिव-सी PoC सोर्स जो विक्टिम क्लोज़ + स्प्रे रीयूज़ अनुक्रम लागू करता है। |
ScalerTeardownUAF.ipa | बिल्ट IPA पुनरुत्पादन आर्टिफैक्ट। |
entitlements.plist | न्यूनतम अधिकार फ़ाइल जिसमें get-task-allow है। |
AppleM2ScalerCSCDriver व्यवहार का परीक्षण करते समय प्रारंभिक क्रैश (crash) मिला।0xDEAD0001, स्प्रे 0xBEEF0002।