
Analyse de course et preuve de concept pour CVE-2026-43805 IOKit IODMACommand
Cette analyse identifie le verrou d'état manquant dans IODMACommand::PerformOperation_Impl d'Apple IOKit, découvert par diff des binaires du noyau macOS 26.5/26.6. Dans les versions vulnérables, CompleteDMA peut libérer le même état pendant que PerformOperation utilise l'état préparé et le descripteur mémoire. Le correctif 26.6 applique également à PerformOperation_Impl le fDextLock déjà partagé par les deux chemins.
État de vérification
Le diff binaire, les cibles d'appel, la correspondance avec les sources XNU publiques et le modèle de course déterministe ont été vérifiés. Le déclencheur DriverKit natif du dépôt a été écrit dans un environnement Linux/WSL et n'a pas encore fait l'objet d'une compilation Xcode ni d'une exécution A/B sur macOS vulnérable/corrigé. Par conséquent, ce dépôt ne prétend pas actuellement avoir observé un panic noyau réel ni une écriture noyau contrôlable.
Apple a classé ce problème comme une condition de course dans IOKit, et indique qu'une application locale peut provoquer un arrêt inattendu du système ou une écriture en mémoire noyau. Le rapporteur est 이재영. Avis de sécurité Apple macOS Tahoe 26.6, Avis de sécurité Apple iOS/iPadOS 26.6
| Produit | Première version corrigée | Paire vulnérable/corrigée utilisée dans l'analyse |
|---|---|---|
| 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 | Version corrigée confirmée uniquement via l'avis |
| macOS Sonoma | 14.8.8 | Version corrigée confirmée uniquement via l'avis |
| watchOS | 26.6 | Version corrigée confirmée uniquement via l'avis |
Les versions corrigées de Sequoia et Sonoma sont consultables respectivement dans l'avis Apple 15.7.8 et l'avis Apple 14.8.8, et watchOS dans l'avis Apple 26.6.
Le 2026-09-27, une recherche combinant l'ID CVE avec PoC, exploit, GitHub, IOKit et le nom du rapporteur n'a permis de trouver ni code de reproduction public ni analyse de la cause. Cette phrase reflète l'observation au moment de la recherche et ne signifie pas qu'un PoC public ne peut absolument pas exister.
Les sources XNU correspondant à la version corrigée n'étant pas publiées, nous avons comparé les noyaux KDK au lieu d'un diff de commits source. La version vulnérable correspond exactement à xnu-12377.121.6 publié par Apple, mais à la date de l'analyse, le tag xnu-12377.161.13 de la version corrigée n'existait pas. Le KDK est un artefact de symboles et de débogage noyau fourni par Apple, et Apple recommande également d'utiliser le KDK correspondant à la version. Guide Apple KDK
Les fichiers utilisés pour la comparaison ne sont pas inclus dans le dépôt.
| Catégorie | Fichier | SHA-256 |
|---|---|---|
| DMG KDK vulnérable | Kernel_Debug_Kit_26.5_build_25F71.dmg | 90ed319cd1ba6e23d1eefcee89fa1b10743f4cf60b85208ae52aa9f45543c7aa |
| DMG KDK corrigé | Kernel_Debug_Kit_26.6_build_25G70.dmg | edaa0b3d431b43ba7dda2f0e82314b19d5476ba4089a7d8c1de18c49b3ad168b |
| Noyau x86_64 vulnérable | XNU 12377.121.6~2 | f4dcaa7e59ae59f3d945c2332862772596b71e9823cc202983ba4f9d897b5bec |
| Noyau x86_64 corrigé | XNU 12377.161.13~4 | 754db65cb15599183ccebfaa2e4909f673de5d7da42ba4293256cb1184587efd |
| kernelcache iOS vulnérable | XNU 12377.122.8~1 | 7bd856548a2d170a5f8c962e9a5740290e5a4ba9a6ac39c96c927d4dd400d890 |
| kernelcache iOS corrigé | XNU 12377.162.13~2 | 680fa3925641e2b81541c8455fc6d8d432acad9f059ac44bb48324791049c9d6 |
tools/diff_macho_symbols.py lit les symboles et sections exécutables Mach-O, restaure les noms C++, puis normalise les cibles de branchement/appel et les adresses relatives à RIP pour comparer les instructions fonction par fonction. Parmi les 19 fonctions modifiées portant un nom IOKit, en excluant les changements de numéros de ligne de diagnostic, le changement de flux de contrôle de IODMACommand::PerformOperation_Impl correspondait à la mention « improved state handling » de l'avis.
IODMACommand::PerformOperation_Impl(...)
vulnerable: 0xffffff8000a39080, 512 bytes
fixed: 0xffffff8000a3b860, 544 bytes
normalized similarity: 0.621429
Les appels suivants sont nouvellement introduits dans le noyau corrigé.
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
Dans les sources publiques vulnérables, PrepareForDMA_Impl et CompleteDMA_Impl acquièrent déjà fDextLock. En revanche, PerformOperation_Impl vérifie fActive puis utilise fMemory, readBytes et writeBytes sans le même verrou.
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
Si CompleteDMA_Impl s'exécute entre la vérification et l'utilisation dans PerformOperation_Impl, l'état préparé initialement vérifié n'est plus valide. fMemory est un OSSharedPtr<IOMemoryDescriptor>, mais ce chemin n'obtient ni référence ni verrou supplémentaire pour protéger l'ensemble de l'opération. Il en résulte que l'état de mémoire DMA libéré ou remplacé peut continuer à être utilisé.
Après le correctif, les trois RPC DMA sérialisent les transitions d'état avec le même verrou.
flowchart LR
P[PrepareForDMA] -->|fDextLock| S[(fActive / fMemory)]
O[PerformOperation] -->|fDextLock 추가| S
C[CompleteDMA] -->|fDextLock| S
L'avis Apple mentionne une écriture en mémoire noyau comme impact possible, mais le seul diff binaire ne démontre pas le contrôle stable de l'adresse et de la valeur écrites. Ce que l'on peut affirmer ici, c'est la condition de course sur la durée de vie/l'état préparé et l'ajout du verrou qui la bloque.
poc/model/race_model.cpp reproduit l'entrelacement problématique sans appeler d'API noyau. Dans le chemin vulnérable, il force le thread de cycle de vie à libérer la mémoire juste après la vérification d'état, et dans le chemin corrigé, il vérifie que le même verrou retarde la libération.
make model
Sortie vérifiée :
vulnerable path: stale memory access = observed
fixed path: stale memory access = not observed
Ce modèle est un PoC auxiliaire qui valide le principe du correctif, et non le résultat réel d'un crash de la vulnérabilité du noyau Apple.