fix(wifi): prevent premature initIvars bypass of super::init and step down to step 2

- Breakthroughs & Rétro-ingénierie :
  * Découverte critique dans IO80211SkywalkInterface::init (0xffffff80022f56e2) :
    L'instruction cmpq $0x0, 0x120(%r14) suivie de jne 0x5733 saute l'appel super::init(0)
    (IOService::init) si ivars est déjà non-nul.
  * L'appel prématuré à initIvars dans createSkywalkInterface laissait donc la classe de base
    IOService non initialisée (fPropertyTable = NULL).
  * Lors de setInterfaceRole(1), setPropertyHelper appelait setProperty sur une table nulle,
    provoquant le bootloop observé au stade 5.

- Modifications apportées :
  * QualcommWifi/QualcommWifi.cpp :
    - Retrait de l'appel à initIvars dans createSkywalkInterface pour laisser 0x120 à NULL
      et garantir l'exécution de super::init(0) par IO80211SkywalkInterface::init.
    - Calibrage du palier par défaut skywalk_step à 2 pour isoler la validation de init().
  * docs/ISSUES_AND_POSTMORTEMS.md : Ajout du rapport post-mortem complet INC-17.

- Validation :
  * Compilation build_wifi.sh réussie à 100%.
  * kmutil libraries validé sans erreur contre BootKernelExtensions.kc.
This commit is contained in:
Erwan committed 2026-10-18 15:53:21 +02:00
1 parent 79d772636f
commit 0519af4666
2 files changed
+39 -5

No files matched your search

+4 -5
View File
@@ -144,7 +144,6 @@ static IO80211SkywalkInterface* createSkywalkInterface(void) {
}
bzero(mem, 0x128);
_ZN23IO80211SkywalkInterfaceC1EPK11OSMetaClass(mem, &_ZN23IO80211SkywalkInterface10gMetaClassE);
_ZN23IO80211SkywalkInterface9initIvarsEv(mem);
return (IO80211SkywalkInterface *)mem;
}
@@ -783,15 +782,15 @@ bool QualcommWifi::start(IOService *provider) {
int allow_skywalk = 1;
PE_parse_boot_argn("qcom_skywalk", &allow_skywalk, sizeof(allow_skywalk));
// Étape maximale Skywalk contrôlée par boot-arg "qcom_step" (par défaut: 5 = attachement IORegistry complet)
// 1: createSkywalkInterface (allocation + initIvars)
// 2: init(this, &mac)
// Étape maximale Skywalk contrôlée par boot-arg "qcom_step" (par défaut: 2 = init complet avec super::init)
// 1: createSkywalkInterface (allocation)
// 2: init(this, &mac) (super::init(0) + initIvars + copy MAC)
// 3: setInterfaceRole(1)
// 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]
int skywalk_step = 5;
int skywalk_step = 2;
PE_parse_boot_argn("qcom_step", &skywalk_step, sizeof(skywalk_step));
if (allow_skywalk) {
+35
View File
@@ -24,6 +24,7 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage
| **INC-14** | Page Fault `CR2: 0x1` dans `printDataPath` | `IO80211SkywalkInterface.h` | Méthodes `init` et `setInterfaceRole` déclarées `virtual` par erreur | **Résolu** |
| **INC-15** | Kernel Trap / Triple Fault dans `initIvars` & `attachInterface` | Skywalk Heap & Attachment ABI | Tas non initialisé (`bzero` manquant), header incorrect, ordre d'attachement et `registerService` prématuré | **Résolu** |
| **INC-16** | Bootloop par démarrage complet Skywalk & Piège de libération `free()` | Skywalk Lifecycle & Ivars Guard | Exécution aveugle du stade 6 (`start`), `#PF` CR2:0xb8 si `free()` sans `initIvars`, et `stop` non-gardé | **Résolu** |
| **INC-17** | Page Fault sur table de propriétés NULL par court-circuit de `super::init(0)` | Skywalk Init Architecture | `initIvars` prématuré faisait croire à `init()` que `super::init(0)` avait déjà eu lieu | **Résolu** |
---
@@ -430,4 +431,38 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage
4. **Validation intégrale de la chaîne de compilation** :
- `build_wifi.sh` validé à 100% avec `kmutil libraries` auprès de `BootKernelExtensions.kc`.
---
### INC-17 : Page Fault sur Table de Propriétés NULL par Court-Circuit de `super::init(0)`
* **Symptômes** :
- Bootloop lors du passage au stade 5 (commit `79d7726`), alors que le stade 1 (commit `b7e32db`) démarrait impeccablement jusqu'au bureau macOS.
* **Causes Racines (Breakthroughs & Rétro-ingénierie du Kernel Collection)** :
1. **Analyse de la condition d'initialisation dans `IO80211SkywalkInterface::init` (`0xffffff80022f56e2`)** :
- Le désassemblage précis montre la logique suivante :
```assembly
0xffffff80022f5710: cmpq $0x0, 0x120(%r14) ; ivars est-il NULL ?
0xffffff80022f5718: jne 0xffffff80022f5733 ; Si NON-NULL, SAUTE super::init(0) !
0xffffff80022f571a: movq 0x15aa07(%rip), %rax ; __ZTV26IOSkywalkEthernetInterface
0xffffff80022f5724: movq %r14, %rdi
0xffffff80022f5729: callq *0x258(%rax) ; super::init(0) -> IOService::init()
0xffffff80022f5733: movq %r14, %rdi
0xffffff80022f5736: callq initIvars ; initIvars()
```
- Dans le commit `b7e32db`/`79d7726`, nous appelions `initIvars` dès `createSkywalkInterface()` pour éviter le piège de `free()`.
- Par conséquent, lors de l'appel à `fSkywalkInterface->init(...)`, `mem + 0x120` était **déjà non-nul** !
- Le saut conditionnel `jne 0x5733` a donc été emprunté, **court-circuitant totalement l'appel `super::init(0)` (`IOService::init()`)** !
2. **Conséquence fatale sur `IOService` et les tables de propriétés** :
- Sans `IOService::init()`, l'infrastructure de base de l'objet (dictionnaire de propriétés `fPropertyTable`, table de registre IORegistry, verrous de synchronisation) n'était pas allouée.
- Dès l'étape suivante (`setInterfaceRole(1)`), le noyau exécutait `setPropertyHelper(this, "IO80211InterfaceRole", ...)` qui tente d'écrire dans la table de propriétés NULL de l'objet, déclenchant un Kernel Page Fault instantané !
* **Résolutions Techniques Appliquées** :
1. **Suppression de l'appel prématuré à `initIvars` dans `createSkywalkInterface`** :
- `createSkywalkInterface` ne fait plus que `operator new` + mise à zéro explicite (`bzero(0x128)`) + constructeur C1.
- `mem + 0x120` reste strictement NULL.
- `fSkywalkInterface->init(...)` constate `0x120 == 0`, invoque légitimement `super::init(0)` pour initialiser `IOService`, puis invoque `initIvars()`.
- L'objet est alors 100% cohérent à la fois côté `IOService` et côté `IO80211SkywalkInterface`.
2. **Calibrage sécurisé du palier par défaut sur l'étape 2 (`skywalk_step=2`)** :
- Permet de valider isolément que `createSkywalkInterface` + `init(this, mac)` démarre avec succès sans risque d'effets de bord ultérieurs.
3. **Validation binaire et dépendances** :
- Compilation `build_wifi.sh` et validation `kmutil libraries` à 100%.