fix(wifi): resolve INC-15 uninitialized heap trap in initIvars and correct Skywalk attachment sequence

### Breakthroughs & Rétro-ingénierie
- **Piège du tas non initialisé (Uninitialized Heap Trap) dans initIvars (0xffffff80022f520c)** :
  - IO80211SkywalkInterfacenwEm(0x128) alloue la mémoire de l'objet via kalloc_type, sans initialisation à zéro.
  - Dans initIvars, le noyau teste si [rdi + 0x120] est nul. En présence de résidus du tas non nuls, le noyau dérive vers le bloc movq 0x120(%rbx), %rdi; callq memset(garbage, 0, 0xf0), déclenchant un Kernel Page Fault (#PF) / Triple Fault instantané.
  - Résolution : bzero(mem, 0x128); systématique avant invocation du constructeur.
- **Header erroné network/IOSkywalkEthernetInterface.h** :
  - Correction de l'héritage fictif d'IOEthernetController vers la hiérarchie Skywalk conforme : IOService -> IOSkywalkInterface -> IOSkywalkNetworkInterface -> IOSkywalkEthernetInterface.
- **Ordre d'attachement Skywalk & contrôleur (Slot 441)** :
  - Broadcom (AppleBCMWLANCore::createSkywalkInterface) appelle attachInterface(fSkywalkInterface, this) au slot 441 avant fSkywalkInterface->attach(this) et start(this), avec this en second paramètre pour renseigner controller->ivars + 0x188 (fPrimaryInterface).
- **Suppression de registerService() prématuré** :
  - Gated derrière qcom_step >= 7 (défaut: 6 = exécution complète de start(this) sans enregistrement prématuré déclenchant le matching IOKit sans buffers).

### Modifications apportées
- QualcommWifi/QualcommWifi.cpp :
  - Ajout de bzero(mem, 0x128) après l'allocation de IO80211SkywalkInterface.
  - Réordonnancement de l'attachement : appel de slot 441 attachInterface(fSkywalkInterface, this) avant attach(this) et start(this).
  - Contrôle d'exécution granulaire par palier via le boot-arg qcom_step (défaut: 6).
- QualcommWireless/include/IOKit/network/IOSkywalkEthernetInterface.h :
  - Redirection propre vers <IOKit/skywalk/IOSkywalkEthernetInterface.h>.
- QualcommWireless/include/IOKit/skywalk/IOSkywalkTypes.h :
  - Ajout du typedef manquant uint32_t kern_packet_svc_class_t.
- docs/ISSUES_AND_POSTMORTEMS.md :
  - Documentation exhaustive du post-mortem INC-15.

### Validation
- Compilation réussie via ./build_wifi.sh.
- Validation des bibliothèques et symboles kmutil libraries -p réussie à 100% contre BootKernelExtensions.kc.
This commit is contained in:
Erwan committed 2026-10-18 14:48:25 +02:00
1 parent c401f7f90c
commit 506df09b68
5 files changed
+113 -35

No files matched your search

+57 -23
View File
@@ -141,10 +141,12 @@ static IO80211SkywalkInterface* createSkywalkInterface(void) {
IOLog("QualcommWifi: Erreur - operator new(IO80211SkywalkInterface) a echoue !\n");
return nullptr;
}
bzero(mem, 0x128);
_ZN23IO80211SkywalkInterfaceC1EPK11OSMetaClass(mem, &_ZN23IO80211SkywalkInterface10gMetaClassE);
return (IO80211SkywalkInterface *)mem;
}
#define super IO80211Controller
OSDefineMetaClassAndStructors(QualcommWifi, IO80211Controller)
@@ -776,42 +778,74 @@ 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: 6 = jusqu'à start(this))
// 1: createSkywalkInterface
// 2: init(this, &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 = 6;
PE_parse_boot_argn("qcom_step", &skywalk_step, sizeof(skywalk_step));
if (allow_skywalk) {
logNvramStage("skywalk_alloc");
fSkywalkInterface = createSkywalkInterface();
if (fSkywalkInterface) {
logNvramStage("skywalk_init");
if (fSkywalkInterface->init(this, (ether_addr *)&fMacAddress)) {
logNvramStage("skywalk_role");
fSkywalkInterface->setInterfaceRole(1); // 1 = kIO80211InterfaceRoleInfra (Primary Wi-Fi)
logNvramStage("skywalk_attach");
if (fSkywalkInterface->attach(this)) {
logNvramStage("skywalk_start");
if (fSkywalkInterface->start(this)) {
IOLog("QualcommWifi: createSkywalkInterface réussi (0x%p) !\n", fSkywalkInterface);
if (skywalk_step >= 2) {
logNvramStage("skywalk_init");
if (fSkywalkInterface->init(this, (ether_addr *)&fMacAddress)) {
IOLog("QualcommWifi: fSkywalkInterface->init(...) réussi !\n");
if (skywalk_step >= 3) {
logNvramStage("skywalk_role");
fSkywalkInterface->setInterfaceRole(1); // 1 = kIO80211InterfaceRoleInfra (Primary Wi-Fi)
IOLog("QualcommWifi: fSkywalkInterface->setInterfaceRole(1) configuré !\n");
}
if (skywalk_step >= 4) {
logNvramStage("skywalk_attach_ctrl");
attachInterface(fSkywalkInterface, nullptr); // slot 441 in IO80211Controller
logNvramStage("skywalk_register");
fSkywalkInterface->registerService();
IOLog("QualcommWifi: Interface Skywalk native (IO80211SkywalkInterface) attachée et enregistrée avec succès !\n");
} else {
logNvramStage("skywalk_start_err");
IOLog("QualcommWifi: Erreur - fSkywalkInterface->start(this) a échoué !\n");
fSkywalkInterface->detach(this);
OSSafeReleaseNULL(fSkywalkInterface);
bool ctrlAttachOk = attachInterface(fSkywalkInterface, this); // slot 441 in IO80211Controller
IOLog("QualcommWifi: this->attachInterface(fSkywalkInterface, this) = %d\n", ctrlAttachOk);
}
if (skywalk_step >= 5) {
logNvramStage("skywalk_attach");
if (fSkywalkInterface->attach(this)) {
IOLog("QualcommWifi: fSkywalkInterface->attach(this) réussi !\n");
if (skywalk_step >= 6) {
logNvramStage("skywalk_start");
if (fSkywalkInterface->start(this)) {
IOLog("QualcommWifi: fSkywalkInterface->start(this) démarré avec succès !\n");
if (skywalk_step >= 7) {
logNvramStage("skywalk_register");
fSkywalkInterface->registerService();
IOLog("QualcommWifi: fSkywalkInterface->registerService() publié !\n");
}
} else {
logNvramStage("skywalk_start_err");
IOLog("QualcommWifi: Erreur - fSkywalkInterface->start(this) a échoué !\n");
fSkywalkInterface->detach(this);
detachInterface(fSkywalkInterface, false);
OSSafeReleaseNULL(fSkywalkInterface);
}
}
} else {
logNvramStage("skywalk_attach_err");
IOLog("QualcommWifi: Erreur - fSkywalkInterface->attach(this) a échoué !\n");
detachInterface(fSkywalkInterface, false);
OSSafeReleaseNULL(fSkywalkInterface);
}
}
} else {
logNvramStage("skywalk_attach_err");
IOLog("QualcommWifi: Erreur - fSkywalkInterface->attach(this) a échoué !\n");
logNvramStage("skywalk_init_err");
IOLog("QualcommWifi: Erreur - fSkywalkInterface->init(...) a échoué !\n");
OSSafeReleaseNULL(fSkywalkInterface);
}
} else {
logNvramStage("skywalk_init_err");
IOLog("QualcommWifi: Erreur - fSkywalkInterface->init(...) a échoué !\n");
OSSafeReleaseNULL(fSkywalkInterface);
}
}
}
int allow_register = 0;
PE_parse_boot_argn("qcom_register", &allow_register, sizeof(allow_register));
@@ -9,8 +9,7 @@
#ifndef _IO80211SKYWALK_H
#define _IO80211SKYWALK_H
#include <Availability.h>
#include <IOKit/network/IOSkywalkEthernetInterface.h>
#include <IOKit/skywalk/IOSkywalkEthernetInterface.h>
// This is necessary, because even the latest Xcode does not support properly targeting 11.0.
#ifndef __IO80211_TARGET
@@ -6,16 +6,10 @@
// Copyright © 2019 钟先耀. All rights reserved.
//
#ifndef _IOSKYWALKINTERFACE_H
#define _IOSKYWALKINTERFACE_H
#ifndef _IOKIT_NETWORK_IOSKYWALKETHERNETINTERFACE_H
#define _IOKIT_NETWORK_IOSKYWALKETHERNETINTERFACE_H
#include <IOKit/network/IOEthernetController.h>
#include <IOKit/skywalk/IOSkywalkEthernetInterface.h>
class IOSkywalkEthernetInterface : public IOEthernetController {
OSDeclareAbstractStructors( IOSkywalkEthernetInterface )
#endif /* _IOKIT_NETWORK_IOSKYWALKETHERNETINTERFACE_H */
public:
};
#endif /* _IOSKYWALKINTERFACE_H */
@@ -31,6 +31,8 @@
#include <IOKit/IOLib.h>
typedef uint32_t kern_packet_svc_class_t;
typedef uint32_t IOSkywalkNetworkLinkStatus;
enum
{
+49
View File
@@ -20,6 +20,9 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage
| **INC-10** | Triple Fault Processeur ("Coupure de Courant") | Logger / CoreCapture | Déréférencement de `+0x90 -> +0x58` dans `CCLogStream::shouldLog` | **Résolu** |
| **INC-11** | Freeze Apple Logo (non-verbose) / Triple Fault (verbose) | NVRAM & Matching IOKit | Matching prématuré de `registerService()` & heap dynamique précoce | **Résolu** |
| **INC-12** | **Triple Fault / Freeze Apple Logo persistant** | `FakeLogStream` / `FakeFaultReporter` | Vtables tronquées à 38 slots (au lieu de 283/269) & `0x88->0x48` Page 0 `#PF` dans `logv` | **Résolu** |
| **INC-13** | Page Fault `CR2: 0x658` dans `ml_thread_policy` au boot | `IOWorkLoop` vs `IO80211WorkQueue` | `IO80211WorkQueue::getThread()` retourne 0, deref `thread->mutex` (+0x658) | **Résolu** |
| **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** |
---
@@ -352,3 +355,49 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage
3. **Conformité des Dépendances** :
- `kmutil libraries -p build/Release/QualcommWifi.kext` valide la résolution intégrale des symboles auprès de `BootKernelExtensions.kc`.
---
### INC-15 : Kernel Trap / Triple Fault dans `initIvars` & Incohérence d'Attachement Skywalk
* **Symptômes** :
- Bootloop persistant et redémarrage brutal de la machine lors de la phase d'instanciation de `IO80211SkywalkInterface`.
- Machine incapable de franchir le stade d'attachement réseau natif sans désactivation manuelle de `QualcommWifi.kext` dans OpenCore.
* **Causes Racines (Breakthroughs & Rétro-ingénierie du Kernel Collection)** :
1. **Piège du tas non initialisé (Uninitialized Heap Trap) dans `initIvars` (`0xffffff80022f520c`)** :
- `_ZN23IO80211SkywalkInterfacenwEm(0x128)` alloue la mémoire de l'objet via `kalloc_type`. Le noyau **ne met pas la mémoire à zéro**.
- Dans le constructeur et dans `IO80211SkywalkInterface::initIvars`, le noyau évalue :
```assembly
0xffffff80022f5215: cmpq $0x0, 0x120(%rdi)
0xffffff80022f521d: je 0xffffff80022f5265 ; Alloue ivars si NULL
...
0xffffff80022f5244: movq 0x120(%rbx), %rdi ; Garbage pointer !
0xffffff80022f524b: movl $0xf0, %esi
0xffffff80022f5250: movl $0xf0, %ecx
0xffffff80022f5255: xorl %edx, %edx
0xffffff80022f5257: callq memset ; memset(garbage, 0, 0xf0) -> Page Fault Ring 0 !
```
- Si `mem + 0x120` contient des résidus non nuls de la mémoire du tas, le noyau tente un `memset` de `0xf0` octets sur cette adresse invalide, causant un Crash Kernel Page Fault / Triple Fault instantané.
2. **Header erroné `network/IOSkywalkEthernetInterface.h`** :
- Le fichier `QualcommWireless/include/IOKit/network/IOSkywalkEthernetInterface.h` déclarait de manière erronée `class IOSkywalkEthernetInterface : public IOEthernetController`.
- Dans l'architecture Apple Skywalk, `IOSkywalkEthernetInterface` hérite en réalité de `IOSkywalkNetworkInterface` -> `IOSkywalkInterface` -> `IOService`, sans aucun lien d'héritage avec `IOEthernetController`.
3. **Ordre d'attachement et second argument du contrôleur (Slot 441)** :
- Dans `AppleBCMWLANCore::createSkywalkInterface` (`0xffffff80016aaa8a`), Apple invoque `this->attachInterface(fSkywalkInterface, this)` (slot 441 d'`IO80211Controller`) **avant** `fSkywalkInterface->attach(this)` et `fSkywalkInterface->start(this)`.
- De plus, le second paramètre transmis doit être `this` (le contrôleur), ce qui renseigne `controller->ivars + 0x188` (`fPrimaryInterface`). L'ancien code passait `nullptr` après `start()`.
4. **Publication prématurée via `registerService()`** :
- Appeler `registerService()` sur `fSkywalkInterface` publie le service auprès du système IOKit matching et d'`airportd` avant que les queues Skywalk et les pools de buffers ne soient négociés, provoquant une panique réseau immédiate.
* **Résolutions Techniques Appliquées** :
1. **Remise à zéro explicite du bloc mémoire avant construction** :
```cpp
void *mem = _ZN23IO80211SkywalkInterfacenwEm(0x128);
if (!mem) return nullptr;
bzero(mem, 0x128);
_ZN23IO80211SkywalkInterfaceC1EPK11OSMetaClass(mem, &_ZN23IO80211SkywalkInterface10gMetaClassE);
```
2. **Correction des inclusions d'en-têtes Skywalk** :
- Redirection du faux header vers `<IOKit/skywalk/IOSkywalkEthernetInterface.h>` et ajout du `typedef uint32_t kern_packet_svc_class_t;` dans `IOSkywalkTypes.h`.
3. **Ordonnancement conforme du cycle d'attachement Skywalk** :
- Invocation de `attachInterface(fSkywalkInterface, this)` au slot 441 avant `attach(this)` et `start(this)`.
4. **Contrôle granulaire d'exécution par palier via le boot-arg `qcom_step`** :
- Introduction du palier `qcom_step` (par défaut `6` = exécution complète de `start(this)` sans appeler prématurément `registerService()`).
- Validation binaire par désassemblage et validation `kmutil libraries` à 100%.