
Divulgación pública para CVE-2026-43655 AppleM2ScalerCSCDriver use-after-free
Divulgación técnica pública para CVE-2026-43655, un uso después de liberación (use-after-free) en AppleM2ScalerCSCDriver / IOSurfaceAccelerator alcanzable desde la sandbox predeterminada de aplicaciones iOS sin permisos especiales.
Apple solucionó este problema en iOS 26.5 / iPadOS 26.5 / macOS Tahoe 26.5. Este repositorio contiene el código fuente de la prueba de concepto (PoC) en Objective-C, los permisos mínimos, un IPA compilado y el informe técnico necesario para comprender y reproducir el problema en un dispositivo afectado.
El error es un fallo de ciclo de vida en el planificador (scheduler) del escalador (scaler). Un proceso de usuario puede enviar operaciones asíncronas del escalador, cerrar la conexión IOSurfaceAcceleratorClient que posee esas operaciones y dejar entradas obsoletas en una estructura del planificador global del controlador. Una pasada posterior del planificador puede procesar entradas que aún apuntan a almacenamiento de operaciones que ya fue liberado y reutilizado.
La PoC demuestra el error de ciclo de vida con dos valores de marcador distintos:
0xDEAD00010xBEEF0002La conexión víctima envía operaciones asíncronas y luego se cierra. Las conexiones de reemplazo se abren después y establecen su propio marcador en 0xBEEF0002. Cuando se ejecuta el siguiente ciclo de planificación del escalador, la falla observa el marcador de reemplazo (x9 = 0x00000000BEEF0002), no el marcador de la víctima. Esto demuestra que el planificador leyó desde una ranura de operación que había sido liberada y luego reasignada a una conexión diferente.
com.apple.driver.AppleM2ScalerCSCDriverIOSurfaceAcceleratorClientget-task-allowAppleM2ScalerCSCDriver mantiene el estado del planificador compartido entre los clientes del escalador. El desajuste de ciclo de vida relevante es:
IOServiceClose.La ruta de destrucción no elimina las entradas pendientes del planificador del cliente que se cierra del montón compartido del planificador. El planificador posteriormente lee y escribe campos a través de esos punteros obsoletos.
Campos importantes observados durante el análisis:
| Desplazamiento | Comportamiento del planificador |
|---|---|
operation + 0xc94 | se lee como el valor de crédito/marcador utilizado por la ruta de resolución de crédito |
operation + 0xc1c | escrito por la ruta de contabilidad de crédito del planificador |
operation + 0x1fe4 | escrito por la ruta de actualización de estado/bandera del planificador |
El comportamiento del asignador de operaciones hace que el error sea observable: las ranuras de operación liberadas pueden ser reutilizadas por operaciones posteriores de diferentes conexiones. Al cerrar una conexión víctima y rociar inmediatamente nuevas conexiones, la PoC puede hacer que las entradas obsoletas del planificador apunten a memoria ahora propiedad de las conexiones de rocío.
x9 = 0xBEEF0002 demuestra UAFLa PoC utiliza una distinción víctima/rocío:
0xDEAD0001.0xBEEF0002.Si el planificador aún estuviera leyendo objetos vivos propiedad de la víctima, el valor observado sería 0xDEAD0001. En cambio, la falla reproducida observa 0xBEEF0002, el valor escrito por las conexiones de rocío de reemplazo. Esa es la prueba clave de que el planificador está desreferenciando un puntero obsoleto hacia memoria del núcleo liberada y reutilizada.
Esto también muestra el impacto entre conexiones: la entrada del planificador fue creada por una conexión, pero la memoria que luego tocó había sido reciclada para otra conexión. En ejecuciones reproducidas, la actividad final del planificador pudo ser impulsada por la actividad normal de SpringBoard/compositor/UI en lugar del proceso original de la PoC.
El aviso público de Apple describe el impacto como: “Una aplicación puede causar una terminación inesperada del sistema o leer memoria del núcleo.”
Detalle importante de reproducción: después de tocar TEARDOWN UAF, el dispositivo no necesariamente entra en pánico inmediatamente. La PoC primero prepara el estado obsoleto del planificador. El error se activa en el siguiente ciclo de planificación del escalador, que en la práctica ocurre cuando la actividad de SpringBoard/compositor impulsa el escalador. En mi reproducción en dispositivo físico, activé ese ciclo de planificación tocando/interactuando con la Dynamic Island después de que la PoC terminara de preparar el estado obsoleto del planificador.
Pasos:
ScalerTeardownUAF.ipa.AppleM2ScalerCSCDriver.IOSurface de origen/destino.0xDEAD0001 en la conexión víctima.IOServiceClose, liberando los objetos de operación propiedad de la víctima mientras las entradas obsoletas del planificador permanecen.0xBEEF0002.x9 = 0x00000000BEEF0002.Condición de prueba esperada:
x9 = 0x00000000BEEF0002 significa que el planificador leyó el marcador de rocío de la memoria que originalmente pertenecía a la operación víctima liberada.0xBEEF0002 no es el marcador de la víctima; es el marcador de la conexión de reemplazo.El código fuente incluido realiza la siguiente secuencia:
abrir conexión víctima
crear par origen/destino IOSurface
enviar solicitud de escalador de línea base síncrona
establecer marcador víctima = 0xDEAD0001 a través del selector 10
enviar 50 operaciones asíncronas del escalador
cerrar conexión víctima
abrir 50 conexiones de rocío
establecer marcador de rocío = 0xBEEF0002 a través del selector 10
enviar operaciones asíncronas del escalador repetidas en las conexiones de rocío
esperar al disparador del planificador de SpringBoard/compositor
El archivo fuente relevante es 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
| Archivo | Descripción |
|---|---|
ScalerTeardownUAF.m | Código fuente de la PoC en Objective-C que implementa la secuencia de cierre de víctima + rocío de reutilización. |
ScalerTeardownUAF.ipa | Artefacto de reproducción IPA compilado. |
entitlements.plist | Archivo de permisos mínimo que contiene get-task-allow. |
AppleM2ScalerCSCDriver.0xDEAD0001, rocío 0xBEEF0002.