fix(wifi): step down default skywalk_step to 1, enforce initIvars allocation, and guard teardown lifecycle
- Breakthroughs & Rétro-ingénierie :
* Découverte critique dans IO80211SkywalkInterface::free() (0xffffff80022f6184) :
La première instruction déréférence ivars + 0xb8 (movq 0x120(%rdi), %rax ; movq 0xb8(%rax), %rdi).
Si l'interface est allouée (operator new + C1) sans que initIvars ne soit exécuté, 0x120 est NULL,
provoquant un Page Fault instantané sur CR2: 0x00000000000000b8 lors de tout release() / stop().
* Dans le commit 506df09, skywalk_step était à 6 par défaut (exécutant d'un coup CCPipe, PM,
IO80211PeerManager, WCLGlue et IO80211MacAddressAgent), ce qui causait le bootloop sans isolation.
* Découverte dans IO80211SkywalkInterface::stop (0xffffff80022f885c) :
Déréférence ivars + 0x80 (movq 0x80(%rax), %rdi). Appeler stop() sans que start() n'ait réussi
déclenche un crash en cascade.
- Modifications apportées :
* QualcommWifi/QualcommWifi.hpp : Ajout des drapeaux d'état de cycle de vie fSkywalkCtrlAttached,
fSkywalkAttached et fSkywalkStarted.
* QualcommWifi/QualcommWifi.cpp :
- Déclaration et appel de _ZN23IO80211SkywalkInterface9initIvarsEv dès createSkywalkInterface pour
garantir la présence immédiate de la structure ivars et immuniser l'objet contre le crash de free().
- Réduction sécurisée du palier par défaut skywalk_step à 1 pour isoler la création de l'objet.
- Protection conditionnelle de l'arrêt dans QualcommWifi::stop() via les drapeaux d'état.
* docs/ISSUES_AND_POSTMORTEMS.md : Documentation détaillée de INC-16.
- Validation :
* Compilation build_wifi.sh réussie à 100%.
* Validation des bibliothèques et symboles avec kmutil libraries réussie sans avertissement.
This commit is contained in:
1 parent
506df09b68
commit
b7e32db90a
3 files changed
+69
-11
No files matched your search
@@ -132,6 +132,7 @@ extern "C" {
|
||||
void* _ZN23IO80211SkywalkInterfacenwEm(unsigned long size);
|
||||
void _ZN23IO80211SkywalkInterfaceC1EPK11OSMetaClass(void *thisPtr, const void *meta);
|
||||
void _ZN23IO80211SkywalkInterfacedlEPvm(void *ptr, unsigned long size);
|
||||
bool _ZN23IO80211SkywalkInterface9initIvarsEv(void *thisPtr);
|
||||
extern const void * const _ZN23IO80211SkywalkInterface10gMetaClassE;
|
||||
}
|
||||
|
||||
@@ -143,6 +144,7 @@ static IO80211SkywalkInterface* createSkywalkInterface(void) {
|
||||
}
|
||||
bzero(mem, 0x128);
|
||||
_ZN23IO80211SkywalkInterfaceC1EPK11OSMetaClass(mem, &_ZN23IO80211SkywalkInterface10gMetaClassE);
|
||||
_ZN23IO80211SkywalkInterface9initIvarsEv(mem);
|
||||
return (IO80211SkywalkInterface *)mem;
|
||||
}
|
||||
|
||||
@@ -166,6 +168,9 @@ bool QualcommWifi::init(OSDictionary *dictionary) {
|
||||
fWorkQueue = nullptr;
|
||||
fNetif = nullptr;
|
||||
fSkywalkInterface = nullptr;
|
||||
fSkywalkCtrlAttached = false;
|
||||
fSkywalkAttached = false;
|
||||
fSkywalkStarted = false;
|
||||
// Adresse MAC par défaut (OUI Qualcomm 00:03:7F) en attendant la lecture BHI
|
||||
fMacAddress.bytes[0] = 0x00;
|
||||
fMacAddress.bytes[1] = 0x03;
|
||||
@@ -778,15 +783,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: 6 = jusqu'à start(this))
|
||||
// 1: createSkywalkInterface
|
||||
// Étape maximale Skywalk contrôlée par boot-arg "qcom_step" (par défaut: 1 = allocation + initIvars sécurisée)
|
||||
// 1: createSkywalkInterface (allocation + initIvars)
|
||||
// 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;
|
||||
int skywalk_step = 1;
|
||||
PE_parse_boot_argn("qcom_step", &skywalk_step, sizeof(skywalk_step));
|
||||
|
||||
if (allow_skywalk) {
|
||||
@@ -805,16 +810,18 @@ bool QualcommWifi::start(IOService *provider) {
|
||||
}
|
||||
if (skywalk_step >= 4) {
|
||||
logNvramStage("skywalk_attach_ctrl");
|
||||
bool ctrlAttachOk = attachInterface(fSkywalkInterface, this); // slot 441 in IO80211Controller
|
||||
IOLog("QualcommWifi: this->attachInterface(fSkywalkInterface, this) = %d\n", ctrlAttachOk);
|
||||
fSkywalkCtrlAttached = attachInterface(fSkywalkInterface, this); // slot 441 in IO80211Controller
|
||||
IOLog("QualcommWifi: this->attachInterface(fSkywalkInterface, this) = %d\n", fSkywalkCtrlAttached);
|
||||
}
|
||||
if (skywalk_step >= 5) {
|
||||
logNvramStage("skywalk_attach");
|
||||
if (fSkywalkInterface->attach(this)) {
|
||||
fSkywalkAttached = true;
|
||||
IOLog("QualcommWifi: fSkywalkInterface->attach(this) réussi !\n");
|
||||
if (skywalk_step >= 6) {
|
||||
logNvramStage("skywalk_start");
|
||||
if (fSkywalkInterface->start(this)) {
|
||||
fSkywalkStarted = true;
|
||||
IOLog("QualcommWifi: fSkywalkInterface->start(this) démarré avec succès !\n");
|
||||
if (skywalk_step >= 7) {
|
||||
logNvramStage("skywalk_register");
|
||||
@@ -824,15 +831,24 @@ bool QualcommWifi::start(IOService *provider) {
|
||||
} else {
|
||||
logNvramStage("skywalk_start_err");
|
||||
IOLog("QualcommWifi: Erreur - fSkywalkInterface->start(this) a échoué !\n");
|
||||
fSkywalkInterface->detach(this);
|
||||
detachInterface(fSkywalkInterface, false);
|
||||
if (fSkywalkAttached) {
|
||||
fSkywalkInterface->detach(this);
|
||||
fSkywalkAttached = false;
|
||||
}
|
||||
if (fSkywalkCtrlAttached) {
|
||||
detachInterface(fSkywalkInterface, false);
|
||||
fSkywalkCtrlAttached = false;
|
||||
}
|
||||
OSSafeReleaseNULL(fSkywalkInterface);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logNvramStage("skywalk_attach_err");
|
||||
IOLog("QualcommWifi: Erreur - fSkywalkInterface->attach(this) a échoué !\n");
|
||||
detachInterface(fSkywalkInterface, false);
|
||||
if (fSkywalkCtrlAttached) {
|
||||
detachInterface(fSkywalkInterface, false);
|
||||
fSkywalkCtrlAttached = false;
|
||||
}
|
||||
OSSafeReleaseNULL(fSkywalkInterface);
|
||||
}
|
||||
}
|
||||
@@ -865,9 +881,18 @@ void QualcommWifi::stop(IOService *provider) {
|
||||
IOLog("QualcommWifi: Arret du pilote Wi-Fi natif, liberation MSI, DMA et BAR0.\n");
|
||||
|
||||
if (fSkywalkInterface) {
|
||||
detachInterface(fSkywalkInterface, false); // slot 442 in IO80211Controller
|
||||
fSkywalkInterface->stop(this);
|
||||
fSkywalkInterface->detach(this);
|
||||
if (fSkywalkCtrlAttached) {
|
||||
detachInterface(fSkywalkInterface, false); // slot 442 in IO80211Controller
|
||||
fSkywalkCtrlAttached = false;
|
||||
}
|
||||
if (fSkywalkStarted) {
|
||||
fSkywalkInterface->stop(this);
|
||||
fSkywalkStarted = false;
|
||||
}
|
||||
if (fSkywalkAttached) {
|
||||
fSkywalkInterface->detach(this);
|
||||
fSkywalkAttached = false;
|
||||
}
|
||||
OSSafeReleaseNULL(fSkywalkInterface);
|
||||
}
|
||||
|
||||
|
||||
@@ -189,6 +189,9 @@ private:
|
||||
IO80211WorkQueue *fWorkQueue;
|
||||
IONetworkInterface *fNetif;
|
||||
IO80211SkywalkInterface *fSkywalkInterface;
|
||||
bool fSkywalkCtrlAttached;
|
||||
bool fSkywalkAttached;
|
||||
bool fSkywalkStarted;
|
||||
IOEthernetAddress fMacAddress;
|
||||
|
||||
// État réseau Wi-Fi
|
||||
|
||||
@@ -23,6 +23,7 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage
|
||||
| **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** |
|
||||
| **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** |
|
||||
|
||||
---
|
||||
|
||||
@@ -400,4 +401,33 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage
|
||||
- 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%.
|
||||
|
||||
---
|
||||
|
||||
### INC-16 : Bootloop par Démarrage Complet Skywalk & Piège de Libération `free()`
|
||||
* **Symptômes** :
|
||||
- Bootloop persistant et redémarrage spontané de la machine lors du chargement de `QualcommWifi.kext` (commit `506df09`).
|
||||
- Nécessité de désactiver manuellement `QualcommWifi.kext` dans OpenCore pour atteindre le bureau macOS.
|
||||
* **Causes Racines (Breakthroughs & Rétro-ingénierie du Kernel Collection)** :
|
||||
1. **Piège de Libération sans `initIvars` dans `IO80211SkywalkInterface::free()` (`0xffffff80022f6184`)** :
|
||||
- Le désassemblage de `IO80211SkywalkInterface::free` révèle :
|
||||
```assembly
|
||||
0xffffff80022f618e: movq 0x120(%rdi), %rax ; rax = ivars
|
||||
0xffffff80022f6195: movq 0xb8(%rax), %rdi ; Déréférencement direct rax + 0xb8 sans vérification NULL !
|
||||
```
|
||||
- Si l'interface est allouée (`operator new + C1`) mais que `initIvars` n'a pas encore été invoqué, `0x120` est `NULL`. Tout appel subséquent à `release()` / `free()` déclenche un Kernel Page Fault instantané sur `CR2: 0x00000000000000b8` !
|
||||
2. **Démarrage complet prématuré par défaut (`skywalk_step=6`)** :
|
||||
- Dans le commit `506df09`, `skywalk_step` était fixé à 6 par défaut. Lors du boot standard (sans boot-arg explicite), le code franchissait d'un coup l'allocation, l'initialisation, le rôle, l'attachement au contrôleur (slot 441), l'attachement IORegistry ET l'appel `fSkywalkInterface->start(this)`.
|
||||
- Dans `start(this)`, Apple initialise `CCPipe`, `CCStream`, `IO80211PeerManager`, la gestion d'énergie `joinPMtree` / `registerPowerDriver` / `changePowerStateTo(0)`, `IO80211Glue`, `WCLGlue`, et `IO80211MacAddressAgent`. Un échec non géré dans ces sous-systèmes sans isolation pas-à-pas provoquait le bootloop.
|
||||
3. **Nettoyage non gardé dans `stop()`** :
|
||||
- `QualcommWifi::stop` invoquait inconditionnellement `detachInterface`, `fSkywalkInterface->stop(this)` et `fSkywalkInterface->detach(this)`. Or, `IO80211SkywalkInterface::stop` déréférence également `ivars + 0x80` (`movq 0x80(%rax), %rdi`), causant un crash en cascade si l'interface n'était pas entièrement démarrée.
|
||||
* **Résolutions Techniques Appliquées** :
|
||||
1. **Invocation explicite et systématique de `initIvars()` dès la création** :
|
||||
- Déclaration et appel de `_ZN23IO80211SkywalkInterface9initIvarsEv(mem)` dans `createSkywalkInterface` dès l'allocation, garantissant que `ivars` est toujours non-nul et immunisé contre tout `#PF` dans `free()`.
|
||||
2. **Réduction sécurisée du palier par défaut à l'étape 1 (`skywalk_step=1`)** :
|
||||
- `int skywalk_step = 1;` par défaut, permettant de valider isolément la stabilité de la création de l'objet avant d'activer les étapes suivantes via `qcom_step`.
|
||||
3. **Protection conditionnelle du cycle de vie dans `stop()` via des drapeaux d'état** :
|
||||
- Ajout de `fSkywalkCtrlAttached`, `fSkywalkAttached`, `fSkywalkStarted` pour ne détacher ou arrêter que ce qui a été effectivement attaché ou démarré avec succès.
|
||||
4. **Validation intégrale de la chaîne de compilation** :
|
||||
- `build_wifi.sh` validé à 100% avec `kmutil libraries` auprès de `BootKernelExtensions.kc`.
|
||||
|
||||
|
||||
Reference in new issue
Block a user