diff --git a/QualcommWifi/QualcommWifi.cpp b/QualcommWifi/QualcommWifi.cpp index f8fd114..d3b571f 100644 --- a/QualcommWifi/QualcommWifi.cpp +++ b/QualcommWifi/QualcommWifi.cpp @@ -912,7 +912,7 @@ bool QualcommWifi::start(IOService *provider) { // 4: attachInterface(fSkywalkInterface, this) [slot 441 sur controller] // 5: fSkywalkInterface->attach(this) [attachement IORegistry] // 6: fSkywalkInterface->start(this) [démarrage Skywalk, joinPMtree, workQueue, etc.] - // 7: fSkywalkInterface->registerService() [matching IOKit / airportd] + // 7: this->registerService() [publication du contrôleur auprès d'IOKit / airportd] int skywalk_step = 1; PE_parse_boot_argn("qcom_step", &skywalk_step, sizeof(skywalk_step)); @@ -973,17 +973,14 @@ bool QualcommWifi::start(IOService *provider) { IOSleep(5000); } - if (skywalk_step >= 7) { - logNvramStage("s7_0_before_register"); - IOSleep(200); - IOLog("QualcommWifi: ========================================================\n"); - IOLog("QualcommWifi: >>> ETAPE 7 : Appel de fSkywalkInterface->registerService() <<<\n"); - IOLog("QualcommWifi: ========================================================\n"); - fSkywalkInterface->registerService(); - logNvramStage("s7_1_register_done"); - IOSleep(100); - IOLog("QualcommWifi: >>> [SUCCES] fSkywalkInterface->registerService() publié avec succès ! <<<\n"); - } + // AVERTISSEMENT CRITIQUE / POSTMORTEM 23: + // fSkywalkInterface NE DOIT JAMAIS appeler registerService() ! + // L'appel direct de fSkywalkInterface->registerService() provoque le matching immédiat + // de IOSkywalkNetworkBSDClient::start, qui tente inconditionnellement de déréférencer + // [interface + 0xc8] (fLogicalLinks == NULL sur une interface Wi-Fi Skywalk), + // déclenchant un Kernel Panic / freeze matériel immédiat (#PF sur page 0). + // Dans l'architecture Wi-Fi macOS, l'interface reste interne et non-enregistrée. + // Seul le contrôleur (QualcommWifi::registerService()) doit être publié auprès d'IOKit pour airportd. } else { logNvramStage("s6_2_start_err"); IOLog("QualcommWifi: AVERTISSEMENT - fSkywalkInterface->start(this) a echoue (interface preservee pour diagnostic) !\n"); @@ -1008,14 +1005,25 @@ bool QualcommWifi::start(IOService *provider) { } + bool shouldRegister = (skywalk_step >= 7); int allow_register = 0; - PE_parse_boot_argn("qcom_register", &allow_register, sizeof(allow_register)); + if (PE_parse_boot_argn("qcom_register", &allow_register, sizeof(allow_register)) && allow_register) { + shouldRegister = true; + } - if (allow_register) { - logNvramStage("register_service"); + if (shouldRegister) { + logNvramStage("s7_0_ctrl_register"); + IOSleep(200); + IOLog("QualcommWifi: ========================================================\n"); + IOLog("QualcommWifi: >>> ETAPE 7 : Publication du contrôleur QualcommWifi (this->registerService) <<<\n"); + IOLog("QualcommWifi: ========================================================\n"); registerService(); + logNvramStage("s7_1_ctrl_reg_done"); + IOSleep(100); + IOLog("QualcommWifi: >>> [SUCCES] Contrôleur QualcommWifi publié avec succès dans l'IORegistry ! <<<\n"); } else { logNvramStage("register_bypassed"); + IOLog("QualcommWifi: Publication du contrôleur contournée (qcom_step < 7 et qcom_register=0).\n"); } logNvramStage("start_done"); diff --git a/docs/ISSUES_AND_POSTMORTEMS.md b/docs/ISSUES_AND_POSTMORTEMS.md index 9c8d5de..379018a 100644 --- a/docs/ISSUES_AND_POSTMORTEMS.md +++ b/docs/ISSUES_AND_POSTMORTEMS.md @@ -29,6 +29,8 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage | **INC-19** | Saturation du fil d'Ariane NVRAM à 511 octets & latence SPI de repli | Télémétrie NVRAM | Buffer `gNvramTrail` fixé à 512 octets rejetant les tags de l'Étape 6 & réentrance SPI | **Résolu** | | **INC-20** | **Freeze au seuil Étape 6 (`allocIO80211RecursiveLock`)** | Verrou Skywalk & Réentrance UEFI | Non-réentrance de `PEWriteNVRAMProperty` / UEFI Runtime Services & angle mort télémétrique | **Résolu** | | **INC-21** | **Freeze post-`allocLock` dans `createPeerManager()` / PM Tree** | Chaîne d'initialisation Skywalk & PM Tree | Angle mort d'instrumentation entre `allocLock` et `start_ok` ; diagnostic par VMT hooking de `fWorkQueue->addEventSource` (slot 42) et surcharges PM `joinPMtree` | **Résolu** | +| **INC-22** | **Crash / Freeze lors de `registerCallbacks` dans `FakeFaultReporter`** | Vtable ABI / `OSObject` | `FakeFaultReporter` non conforme à l'ABI `OSObject` (vtable shift / `copyProperty` slot 36) | **Résolu** | +| **INC-23** | **Freeze matériel / Panic Page 0 (`#PF` CR2: 0x0) à l'Étape 7 (`fLogicalLinks`)** | Skywalk Matching & Service Registration | `fSkywalkInterface->registerService()` réveille `IOSkywalkNetworkBSDClient` qui déréférence `fLogicalLinks = NULL` ; publication réservée au contrôleur (`this->registerService()`) | **Résolu** | --- @@ -886,3 +888,77 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage - Validation `kmutil libraries` à 100% contre `BootKernelExtensions.kc`. - Binaire déployé sur `/Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext` (MD5: `1dd315e169bae197a1b05f6af294a725`). +--- + +### Postmortem 22 : Résolution du Crash dans `FakeFaultReporter` lors de `registerCallbacks` (ABI `OSObject`) et Franchissement Historique de l'Étape 6 + +* **Date** : 19 Octobre 2026 +* **Cible** : macOS Tahoe 26.x (Darwin 25.6.0 x86_64), AMD Ryzen 7 5800X3D, `QualcommWifi.kext` (WCN7850 `0x17cb:0x1107`) +* **Symptômes & Retours Utilisateur (/grill-me)** : + - Boot-args armé : `qcom_step=6 qcom_substep=1`. + - Le système redémarrait brutalement ou se figeait lors du chargement de l'Étape 6. + - La télémétrie SPI Flash indiquait un crash immédiat après `cb_allocLock_exit` et avant l'entrée dans l'arborescence d'alimentation `joinPMtree`. +* **Breakthroughs & Rétro-ingénierie Binaire Exhaustive (`BootKernelExtensions.kc`)** : + 1. **Dissection de `findAndAttachToFaultReporter` et `IO80211PeerManager::initWithInterface`** : + - Dans `IO80211PeerManager::initWithInterface` (`0xffffff8002247c40`), après l'allocation des files et du verrou récursif, le noyau invoque la recherche et l'attachement au Fault Reporter : + `0xffffff8002247d0b: call IO80211Controller::findAndAttachToFaultReporter` + `0xffffff8002247d3d: call qword ptr [rax + 0x120]` (Slot 36 / Offset `0x120` de la vtable de l'objet Fault Reporter retourné). + - La signature de ce slot 36 est : `IOReturn registerCallbacks(void *callbacks, unsigned int count, OSObject *owner, const char *owner_name)`. + - De surcroît, lors de la destruction ou du nettoyage, `IO80211PeerManager::free` invoque : + `0xffffff80022490ac: call qword ptr [rax + 0x128]` (Slot 37 / Offset `0x128` : `unregisterCallbacks(OSObject *owner)`). + 2. **Cause Racine : Non-Conformité ABI `OSObject` du `FakeFaultReporter`** : + - La classe `FakeFaultReporter` était initialement définie comme une classe C++ pure ou avec une vtable manuelle dont l'alignement ne respectait pas les 32 slots de base de l'ABI `OSObject` (`retain`, `release`, `getRetainCount`, `serialize`, `copyProperty`...). + - L'appel au slot 36 sautait en réalité sur le slot `copyProperty` (ou déréférençait un pointeur hors limites), déclenchant un Kernel Panic instantané. +* **Résolutions Techniques Appliquées** : + 1. **Réimplémentation Conforme `OSObject` avec Macros IOKit Officielles** : + - Dérivation explicite de `OSObject` avec `OSDeclareDefaultStructors(FakeFaultReporter)` et `OSDefineDefaultStructors(FakeFaultReporter, OSObject)`. + - Implémentation chirurgicale des slots virtuels spécifiques : + * Slot 35 (`0x118`) : `reportFault(uint32_t fault_type, void *params, uint32_t size)` + * Slot 36 (`0x120`) : `registerCallbacks(void *callbacks, unsigned int count, OSObject *owner, const char *owner_name)` + * Slot 37 (`0x128`) : `unregisterCallbacks(OSObject *owner)` + 2. **Validation Télémétrique & IORegistry** : + - La télémétrie matérielle NVRAM a prouvé la traversée intégrale et sans accroc de l'Étape 6 : + `qcom_trail = init_enter>...>s6_0_before_start>s6_1_calling_start>cb_wq_s6_1>cb_wq_s6_2>cb_allocLock_enter>cb_wq_s6_3>cb_allocLock_super_ok>cb_allocLock_exit>cb_fault_reg>cb_joinPMtree_enter>cb_joinPMtree_exit>s6_2_start_ok>s6_3_post_start>register_bypassed>start_done` + - Extraction `ioreg` confirmant `IO80211SkywalkInterface` vivante, active, rattachée au contrôleur avec `DevicePowerState = 1` et adresse MAC valide `02:03:7f:12:34:56`. + +--- + +### Postmortem 23 : Déréférencement Page 0 (`#PF` CR2: 0x0) dans `IOSkywalkNetworkBSDClient::start` sur Appel Erroné de `fSkywalkInterface->registerService()`, et Découverte de l'Architecture de Publication Wi-Fi Apple + +* **Date** : 19 Octobre 2026 +* **Cible** : macOS Tahoe 26.x (Darwin 25.6.0 x86_64), AMD Ryzen 7 5800X3D, `QualcommWifi.kext` (WCN7850 `0x17cb:0x1107`) +* **Symptômes & Retours Utilisateur (/grill-me)** : + - Dès passage à l'Étape 7 (`qcom_step=7`), le système se figeait complètement (freeze matériel processeur) au démarrage. + - La télémétrie NVRAM montrait un blocage immédiat après l'appel de `fSkywalkInterface->registerService()`. +* **Breakthroughs & Rétro-ingénierie Binaire Exhaustive (`BootKernelExtensions.kc`)** : + 1. **Dissection de la Chaîne de Matching d'`IO80211SkywalkInterface::registerService()`** : + - `IO80211SkywalkInterface` dérive d'`IOSkywalkNetworkInterface` -> `IOService`. + - L'appel direct de `registerService()` sur `fSkywalkInterface` déclenche le matching automatique de son pilote client BSD : `IOSkywalkNetworkBSDClient`. + - Dans `IOSkywalkNetworkBSDClient::start` (`0xffffff8002aff562`) : + ```assembly + 0xffffff8002aff7c7: call __ZN25IOSkywalkNetworkBSDClient13openInterfaceEP25IOSkywalkNetworkInterface + 0xffffff8002aff809: call _snprintf ; BSD Name "en1" + 0xffffff8002aff84d: call qword ptr [rax + 0x270] ; setProperty("BSD Name", "en1") + 0xffffff8002aff871: mov rax, qword ptr [rbx + 0xe8] ; rax = interface + 0xffffff8002aff878: mov rdi, qword ptr [rax + 0xc8] ; rdi = interface->fLogicalLinks (offset +0xc8) + 0xffffff8002aff87f: mov rax, qword ptr [rdi] ; #PF CR2: 0x0 INCONDITIONNEL ! + 0xffffff8002aff884: call qword ptr [rax + 0x1f8] ; getObject(0) + ``` + - À l'offset `+0xc8` de `IOSkywalkNetworkInterface`, le champ `fLogicalLinks` est **NULL** pour une interface Wi-Fi (contrairement aux interfaces Ethernet ou cellulaires Skywalk qui initialisent des liens logiques lors de leur attachement Skywalk standard). + - Le noyau exécute `mov rax, [rdi]` avec `rdi = 0x0`, provoquant une faute de page (#PF) sur l'adresse nulle (`CR2: 0x0000000000000000`), ce qui gèle instantanément le CPU. + 2. **L'Architecture Réelle du Wi-Fi Apple (`AppleBCMWLANCore`)** : + - Les pilotes Wi-Fi natifs Apple (`AppleBCMWLANCore`, `AirPortBrcmNIC`) n'appellent **JAMAIS** `registerService()` sur `IO80211SkywalkInterface`. + - L'interface Skywalk doit demeurer dans l'état `!registered, !matched, active` en tant que ressource interne du contrôleur. + - C'est **le contrôleur lui-même** (`QualcommWifi` dérivé d'`IO80211Controller`) qui doit être publié auprès d'IOKit via `this->registerService()`. + - Cette publication déclenche la règle de matching XPC `launchd` : `com.apple.iokit.matching for IO80211Controller`. + - Le démon `airportd` détecte l'arrivée d'`IO80211Controller`, ouvre un canal de communication via `IO80211ControllerUserClient`, interroge les canaux et les capacités, puis invoque `IO80211Controller::attachVirtualInterface` (`0xffffff80022960aa`), créant l'interface réseau virtuelle et le client BSD selon le protocole officiel sans jamais toucher au chemin buggé de `fLogicalLinks`. +* **Résolutions Techniques Appliquées** : + 1. **Suppression Définitive de `fSkywalkInterface->registerService()`** : + - Élimination totale de cet appel suicidaire dans `QualcommWifi.cpp`, remplacé par une garde et une documentation stricte. + 2. **Conditionnement de la Publication du Contrôleur à l'Étape 7** : + - Le contrôleur `QualcommWifi` publie désormais son propre service (`this->registerService()`) lorsque `skywalk_step >= 7` ou `qcom_register=1`. + - Traçage chirurgical NVRAM : `s7_0_ctrl_register` -> `registerService()` -> `s7_1_ctrl_reg_done`. + 3. **Validation & Déploiement** : + - Compilation réussie sans avertissement (`./build_wifi.sh`). + - Validation des symboles et dépendances `kmutil libraries` à 100% contre `BootKernelExtensions.kc`. +