
CVE-2026-43805 análise de corrida e prova de conceito do IOKit IODMACommand
Esta é uma análise da ausência de bloqueio de estado em IODMACommand::PerformOperation_Impl do Apple IOKit, descoberta por meio de diff de binários do kernel do macOS 26.5/26.6. Em builds vulneráveis, CompleteDMA pode liberar o mesmo estado enquanto PerformOperation está usando o estado de preparação e o descritor de memória. O patch do 26.6 aplica o fDextLock, que já era compartilhado pelos dois caminhos, também ao PerformOperation_Impl.
Status de verificação
O diff de binários, os alvos de chamada, o mapeamento com o código-fonte público do XNU e o modelo determinístico de corrida foram verificados. O gatilho nativo de DriverKit do repositório foi escrito em ambiente Linux/WSL e ainda não passou por build no Xcode nem por execução A/B em macOS vulnerável/patcheado. Portanto, este repositório atualmente não afirma ter observado um kernel panic real nem um kernel write controlável.
A Apple classificou este problema como uma race condition do IOKit e descreve que um app local pode causar encerramento inesperado do sistema ou escrita em memória do kernel. O relator é 이재영. Aviso de segurança do Apple macOS Tahoe 26.6, Aviso de segurança do Apple iOS/iPadOS 26.6
| Produto | Versão com correção inicial | Par vulnerável/corrigido usado na análise |
|---|---|---|
| iOS / iPadOS | 26.6 | iPhone 11: 26.5.2 (23F84) → 26.6 (23G71) |
| macOS Tahoe | 26.6 | KDK 26.5 (25F71) → KDK 26.6 (25G70) |
| macOS Sequoia | 15.7.8 | Apenas versão corrigida confirmada pelo aviso |
| macOS Sonoma | 14.8.8 | Apenas versão corrigida confirmada pelo aviso |
| watchOS | 26.6 | Apenas versão corrigida confirmada pelo aviso |
As versões corrigidas do Sequoia e do Sonoma podem ser confirmadas, respectivamente, no aviso do Apple 15.7.8 e no aviso do Apple 14.8.8, e o watchOS no aviso do Apple 26.6.
Em 2026-09-27, foram feitas buscas combinando o CVE ID com PoC, exploit, GitHub, IOKit e o nome do relator, mas não foi encontrado código de reprodução público nem análise de causa raiz. Esta frase é uma observação do momento da busca e não significa que um PoC público jamais exista.
Como o código-fonte do XNU correspondente à versão corrigida não foi publicado, comparamos os kernels do KDK em vez do diff de commits do código-fonte. O lado vulnerável corresponde exatamente ao xnu-12377.121.6 publicado pela Apple, mas, na data da análise, não havia a tag xnu-12377.161.13 do lado corrigido. O KDK é um artefato de símbolos e depuração de kernel fornecido pela Apple, e a Apple também orienta o uso do KDK correspondente à versão. Guia do Apple KDK
Os arquivos usados na comparação não estão incluídos no repositório.
| Categoria | Arquivo | SHA-256 |
|---|---|---|
| DMG do KDK vulnerável | Kernel_Debug_Kit_26.5_build_25F71.dmg | 90ed319cd1ba6e23d1eefcee89fa1b10743f4cf60b85208ae52aa9f45543c7aa |
| DMG do KDK corrigido | Kernel_Debug_Kit_26.6_build_25G70.dmg | edaa0b3d431b43ba7dda2f0e82314b19d5476ba4089a7d8c1de18c49b3ad168b |
| Kernel x86_64 vulnerável | XNU 12377.121.6~2 | f4dcaa7e59ae59f3d945c2332862772596b71e9823cc202983ba4f9d897b5bec |
| Kernel x86_64 corrigido | XNU 12377.161.13~4 | 754db65cb15599183ccebfaa2e4909f673de5d7da42ba4293256cb1184587efd |
| kernelcache iOS vulnerável | XNU 12377.122.8~1 | 7bd856548a2d170a5f8c962e9a5740290e5a4ba9a6ac39c96c927d4dd400d890 |
| kernelcache iOS corrigido | XNU 12377.162.13~2 | 680fa3925641e2b81541c8455fc6d8d432acad9f059ac44bb48324791049c9d6 |
tools/diff_macho_symbols.py lê símbolos e seções executáveis do Mach-O, restaura nomes C++, normaliza destinos de desvios/chamadas e endereços relativos a RIP, e compara as instruções por função. Entre as 19 funções alteradas com nomes do IOKit, excluindo mudanças em números de linha de diagnóstico, a mudança no fluxo de controle de IODMACommand::PerformOperation_Impl correspondeu ao “improved state handling” do aviso.
IODMACommand::PerformOperation_Impl(...)
vulnerable: 0xffffff8000a39080, 512 bytes
fixed: 0xffffff8000a3b860, 544 bytes
normalized similarity: 0.621429
A seguinte chamada é adicionada no kernel corrigido.
mov rax, [r14 + 0x70] ; IODMACommand::reserved
mov rdi, [rax + 0xc0] ; IODMACommandInternal::fDextLock
call IOLockLock
; fActive 확인 및 readBytes/writeBytes 작업
mov rax, [r14 + 0x70]
mov rdi, [rax + 0xc0]
call IOLockUnlock
Observando o código-fonte público vulnerável, PrepareForDMA_Impl e CompleteDMA_Impl já adquirem fDextLock. Por outro lado, PerformOperation_Impl verifica fActive e depois usa fMemory, readBytes e writeBytes sem o mesmo lock.
sequenceDiagram
participant A as Worker A: PerformOperation
participant C as IODMACommand state
participant B as Worker B: CompleteDMA
A->>C: fActive == true 확인
A->>A: 임시 버퍼 할당/준비
B->>C: fDextLock 획득
B->>C: complete(), fActive 감소
B->>C: clearMemoryDescriptor(), fMemory 해제
B-->>C: fDextLock 해제
A->>C: readBytes/writeBytes에서 fMemory 사용
Note over A,C: 상태 검사와 사용 사이 TOCTOU
Se CompleteDMA_Impl for executado entre a verificação e o uso em PerformOperation_Impl, o estado de preparação verificado inicialmente deixa de ser válido. fMemory é OSSharedPtr<IOMemoryDescriptor>, mas esse caminho não obtém uma referência ou lock separado para proteger toda a operação. Como resultado, o estado da memória DMA liberada ou substituída pode continuar sendo usado.
Após o patch, os três RPCs de DMA serializam as transições de estado com o mesmo lock.
flowchart LR
P[PrepareForDMA] -->|fDextLock| S[(fActive / fMemory)]
O[PerformOperation] -->|fDextLock 추가| S
C[CompleteDMA] -->|fDextLock| S
O aviso da Apple especifica kernel-memory write como possível impacto, mas apenas com o diff de binários não se comprova controle estável de endereço/valor de escrita. O que se pode confirmar aqui é a corrida de tempo de vida/estado de preparação e a adição do lock que a impede.
poc/model/race_model.cpp reproduz o interleaving problemático sem chamar APIs do kernel. No caminho vulnerável, força a thread de lifecycle a liberar a memória logo após a verificação de estado; no caminho corrigido, verifica se o mesmo lock atrasa a liberação.
make model
Saída verificada:
vulnerable path: stale memory access = observed
fixed path: stale memory access = not observed
Este modelo é um PoC auxiliar que verifica o princípio do patch e não é o resultado real de colisão da vulnerabilidade do kernel da Apple.