fix(skywalk): injecter IFRTYPE_SUBFAMILY_WIFI (3) et medium 802.11Auto pour Apple80211GetIfListCopy
Breakthroughs & Rétro-ingénierie : - Dissection sous LLDB de _getIfListCopy (0x7ffc267b58fb dans Apple80211.framework) : 1. Filtre SIOCGIFTYPE (0xc020699f) : vérifie ifr.ifru_type.ift_type == 6 (IFT_ETHER) ET ifr.ifru_type.ift_subfamily == 3 (IFRTYPE_SUBFAMILY_WIFI / net/if_private.h). Si ift_subfamily != 3 (notre interface renvoyait 0 par défaut), l'interface est immédiatement et silencieusement rejetée sans figurer dans le CFArray de sortie. 2. Filtre SIOCGIFMEDIA (0xc02c6938) : vérifie (ifmr.ifm_current & 0xe0) == 0x80 (IFM_IEEE80211). Si non conforme (renvoyait 0x20 / IFM_ETHER), rejet direct. - Dissection dans BootKernelExtensions.kc de IOSkywalkEthernetInterface::initRegistrationInfo (0xffffff8002b108e2) et registerNetworkInterfaceWithLogicalLink (0xffffff8002b0a204) : Le noyau copie fidèlement fSkywalkRegInfo dans priv->regInfo. initBSDInterfaceParameters lit getInterfaceSubFamily() (slot 0x9a8) qui lit priv->regInfo + 0x0c pour initialiser eparams->subfamily et ifp->if_subfamily dans BSD. Modifications apportées : - QualcommWifi/QualcommWifi.cpp : * Dans substep 8.1 : configuration de fSkywalkRegInfo + 0x0c à 3 (IFRTYPE_SUBFAMILY_WIFI), fSkywalkRegInfo + 0x24 et +0x28 à 0x80 (kIOMediumIEEE80211Auto), et MTU à 1500. * Dans substeps 8.4 et 8.5 : configuration chirurgicale de priv->regInfo et struct ifmedia (status=0x3, current=0x80, active=0x80) à fSkywalkInterface + 0xc0. * Dans createMediumTables() : publication exclusive du médium kIOMediumIEEE80211Auto (1.2 Gbps) pour éliminer tout résidu Ethernet. - docs/ISSUES_AND_POSTMORTEMS.md : * Rédaction complète du Postmortem 26 avec analyse d'assemblage et justification technique. Validation : - Compilation Release x86_64 validée à 100% avec ./build_wifi.sh. - Validation des dépendances kmutil libraries réussie sans avertissement contre BootKernelExtensions.kc. - Kext déployé sur /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext (MD5: 918e6727043a53bbe4825671f428ab5c).
This commit is contained in:
1 parent
5efd0dfbae
commit
25e41914f9
2 files changed
+133
-21
No files matched your search
@@ -1090,11 +1090,24 @@ bool QualcommWifi::start(IOService *provider) {
|
||||
fSkywalkInterface, fSkywalkRegInfo, 1, sizeof(fSkywalkRegInfo)
|
||||
);
|
||||
if (regInit) {
|
||||
// Configuration de l'adresse MAC physique et MTU
|
||||
// 1. Définir le sous-type réseau BSD en Wi-Fi (IFRTYPE_SUBFAMILY_WIFI = 3)
|
||||
// Découverte chirurgicale / Postmortem 26 :
|
||||
// Apple80211.framework (_getIfListCopy) appelle ioctl(SIOCGIFTYPE, 0xc020699f).
|
||||
// Il exige ifr.ifru_type.ift_type == 6 (IFT_ETHER) et ifr.ifru_type.ift_subfamily == 3 (IFRTYPE_SUBFAMILY_WIFI).
|
||||
// Sans cette valeur (0 par défaut sur Skywalk Ethernet), Apple80211 rejette silencieusement en1 !
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x0c) = 3; // IFRTYPE_SUBFAMILY_WIFI = 3
|
||||
|
||||
// 2. Définir le type de médium sur IEEE 802.11 Auto (0x80)
|
||||
// Apple80211.framework vérifie également (ifmr.ifm_current & 0xe0) == 0x80 (IFM_IEEE80211).
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x24) = 0x80; // active medium: kIOMediumIEEE80211Auto
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x28) = 0x80; // current medium: kIOMediumIEEE80211Auto
|
||||
|
||||
// 3. Configuration de l'adresse MAC physique et MTU
|
||||
memcpy(fSkywalkRegInfo + 0x108, fMacAddress.bytes, 6);
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x48) = 1500;
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x4c) = 1500;
|
||||
logNvramStage("s8_1_reginfo_ok");
|
||||
IOLog("QualcommWifi: [s8_1] initRegistrationInfo réussi et MAC configurée !\n");
|
||||
IOLog("QualcommWifi: [s8_1] initRegistrationInfo configuré (subfamily=WIFI/3, medium=802.11Auto/0x80, MAC OK) !\n");
|
||||
} else {
|
||||
logNvramStage("s8_1_reginfo_err");
|
||||
IOLog("QualcommWifi: [s8_1] ERREUR initRegistrationInfo !\n");
|
||||
@@ -1155,6 +1168,22 @@ bool QualcommWifi::start(IOService *provider) {
|
||||
IOLog("QualcommWifi: ========================================================\n");
|
||||
IOLog("QualcommWifi: >>> [SUCCES MAJEUR] registerEthernetInterface A REUSSI ! <<<\n");
|
||||
IOLog("QualcommWifi: ========================================================\n");
|
||||
|
||||
// Postmortem 26 : Configuration des structures internes de fSkywalkInterface
|
||||
// fSkywalkInterface + 0xc0 pointe sur priv
|
||||
uint8_t *priv = *(uint8_t **)((uint8_t *)fSkywalkInterface + 0xc0);
|
||||
if (priv) {
|
||||
uint8_t *regInfo = *(uint8_t **)priv;
|
||||
if (regInfo) {
|
||||
*(uint32_t *)(regInfo + 0x0c) = 3; // IFRTYPE_SUBFAMILY_WIFI = 3
|
||||
*(uint32_t *)(regInfo + 0x24) = 0x80; // active medium: kIOMediumIEEE80211Auto
|
||||
*(uint32_t *)(regInfo + 0x28) = 0x80; // current medium: kIOMediumIEEE80211Auto
|
||||
}
|
||||
*(uint32_t *)(priv + 0x30) = 0x3; // ifm_status = IFM_AVALID | IFM_ACTIVE (1 | 2)
|
||||
*(uint32_t *)(priv + 0x34) = 0x80; // ifm_current = kIOMediumIEEE80211Auto (0x80)
|
||||
*(uint32_t *)(priv + 0x38) = 0x80; // ifm_active = kIOMediumIEEE80211Auto (0x80)
|
||||
IOLog("QualcommWifi: [s8_4] struct ifmedia (status=0x3, current=0x80, active=0x80) et regInfo configurés !\n");
|
||||
}
|
||||
} else {
|
||||
logNvramStage("s8_4_reg_eth_err");
|
||||
IOLog("QualcommWifi: [s8_4] registerEthernetInterface a échoué (0x%x) !\n", regRes);
|
||||
@@ -1171,6 +1200,14 @@ bool QualcommWifi::start(IOService *provider) {
|
||||
logNvramStage("s8_6_reg_svc_done");
|
||||
IOSleep(100);
|
||||
IOLog("QualcommWifi: >>> [SUCCES TOTAL] Service Skywalk publié, création d'en1 imminente ! <<<\n");
|
||||
|
||||
// Ré-application post-enregistrement pour garantir la persistance de l'état média
|
||||
uint8_t *priv = *(uint8_t **)((uint8_t *)fSkywalkInterface + 0xc0);
|
||||
if (priv) {
|
||||
*(uint32_t *)(priv + 0x30) = 0x3; // ifm_status = IFM_AVALID | IFM_ACTIVE
|
||||
*(uint32_t *)(priv + 0x34) = 0x80; // ifm_current = kIOMediumIEEE80211Auto
|
||||
*(uint32_t *)(priv + 0x38) = 0x80; // ifm_active = kIOMediumIEEE80211Auto
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1338,8 +1375,8 @@ IOReturn QualcommWifi::disable(IONetworkInterface *netif) {
|
||||
}
|
||||
|
||||
bool QualcommWifi::createMediumTables(void) {
|
||||
IOLog("QualcommWifi: Creation et publication du dictionnaire de mediums reseau...\n");
|
||||
OSDictionary *mediumDict = OSDictionary::withCapacity(2);
|
||||
IOLog("QualcommWifi: Creation et publication du dictionnaire de mediums reseau IEEE 802.11...\n");
|
||||
OSDictionary *mediumDict = OSDictionary::withCapacity(1);
|
||||
if (!mediumDict) {
|
||||
IOLog("QualcommWifi: ERREUR allocation mediumDict !\n");
|
||||
return false;
|
||||
@@ -1347,39 +1384,25 @@ bool QualcommWifi::createMediumTables(void) {
|
||||
|
||||
IONetworkMedium *mediumWifi = IONetworkMedium::medium(
|
||||
kIOMediumIEEE80211Auto,
|
||||
1000000000ULL, // 1 Gbps
|
||||
1200000000ULL, // 1.2 Gbps (Wi-Fi 7 / 6E)
|
||||
0,
|
||||
0,
|
||||
"Auto"
|
||||
);
|
||||
IONetworkMedium *mediumEth = IONetworkMedium::medium(
|
||||
kIOMediumEthernetAuto,
|
||||
1000000000ULL,
|
||||
0,
|
||||
1,
|
||||
"EthernetAuto"
|
||||
);
|
||||
|
||||
if (mediumWifi) {
|
||||
IONetworkMedium::addMedium(mediumDict, mediumWifi);
|
||||
mediumWifi->release();
|
||||
}
|
||||
if (mediumEth) {
|
||||
IONetworkMedium::addMedium(mediumDict, mediumEth);
|
||||
mediumEth->release();
|
||||
}
|
||||
|
||||
bool published = publishMediumDictionary(mediumDict);
|
||||
if (published) {
|
||||
const IONetworkMedium *selected = IONetworkMedium::getMediumWithType(mediumDict, kIOMediumIEEE80211Auto);
|
||||
if (!selected) {
|
||||
selected = IONetworkMedium::getMediumWithType(mediumDict, kIOMediumEthernetAuto);
|
||||
}
|
||||
if (selected) {
|
||||
setSelectedMedium(selected);
|
||||
setCurrentMedium(selected);
|
||||
setLinkStatus(kIONetworkLinkValid | kIONetworkLinkActive, selected, 1000000000ULL, nullptr);
|
||||
IOLog("QualcommWifi: Medium selectionne et linkStatus(Active) configure avec succes !\n");
|
||||
setLinkStatus(kIONetworkLinkValid | kIONetworkLinkActive, selected, 1200000000ULL, nullptr);
|
||||
IOLog("QualcommWifi: Medium IEEE80211Auto selectionne et linkStatus(Active) configure avec succes !\n");
|
||||
}
|
||||
} else {
|
||||
IOLog("QualcommWifi: ERREUR publishMediumDictionary !\n");
|
||||
|
||||
@@ -1060,3 +1060,92 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage
|
||||
- Binaire déployé sur `/Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext` (MD5: `480ca02aff49c48afbe8b381be0c3c77`).
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
### Postmortem 26 : Rétro-ingénierie Chirurgicale d'`Apple80211GetIfListCopy` : Résolution du Filtre `SIOCGIFTYPE` (`IFRTYPE_SUBFAMILY_WIFI = 3`) et `SIOCGIFMEDIA` (`IFM_IEEE80211 = 0x80`)
|
||||
|
||||
* **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émarrage 100% stable sans freeze ni crash validé avec l'Étape 8 (`qcom_step=8 qcom_substep=5`).
|
||||
- L'interface `en1` existe dans le système (`ifconfig en1`), et `SIOCGIFXMEDIA: Input/output error` a été éliminée à 100% (`media: autoselect (none)`).
|
||||
- Cependant, l'icône Wi-Fi ne s'allume pas dans le menu macOS, et `Apple80211GetIfListCopy` renvoie l'erreur `-3903` (`0xfffff0c1`), empêchant `airportd` d'associer `en1`.
|
||||
* **Breakthroughs & Rétro-ingénierie Binaire Exhaustive (`Apple80211.framework` & `BootKernelExtensions.kc`)** :
|
||||
1. **Dissection Chirurgicale de `_getIfListCopy` (`0x7ffc267b58fb`) sous LLDB** :
|
||||
- L'analyse pas-à-pas des instructions de `_getIfListCopy` lors de l'énumération `getifaddrs()` a révélé **deux filtres matériels stricts et cumulatifs** appliqués à chaque interface réseau :
|
||||
- **Filtre 1 : Le Contrôle de Type BSD `SIOCGIFTYPE` (`0xc020699f`)** :
|
||||
```assembly
|
||||
0x7ffc267b5dda: movl $0xc020699f, %esi ; ioctl(fd, SIOCGIFTYPE, &ifr)
|
||||
0x7ffc267b5de4: callq ioctl
|
||||
...
|
||||
0x7ffc267b5fd9: cmpl $0x6, -0xc0(%rbp) ; ifr.ifru_type.ift_type == 6 (IFT_ETHER)
|
||||
0x7ffc267b5fee: jne 0x7ffc267b6091 ; Si != 6 -> IGNORE SILENCIEUSEMENT L'INTERFACE !
|
||||
0x7ffc267b5ff4: cmpl $0x3, -0xb8(%rbp) ; ifr.ifru_type.ift_subfamily == 3 (IFRTYPE_SUBFAMILY_WIFI) !
|
||||
0x7ffc267b5ffb: je 0x7ffc267b6024 ; Si == 3 -> AJOUTE DIRECTEMENT en1 AU CFArray DE SUCCÈS !
|
||||
0x7ffc267b5ffd: jmp 0x7ffc267b6091 ; Si != 3 -> IGNORE L'INTERFACE !
|
||||
```
|
||||
* Définition dans `net/if_private.h` :
|
||||
```c
|
||||
#define IFRTYPE_SUBFAMILY_WIFI 3
|
||||
```
|
||||
* Sur notre interface `en1`, `SIOCGIFTYPE` renvoyait `ift_type: 6, ift_family: 2, ift_subfamily: 0`.
|
||||
* En raison de `ift_subfamily == 0` au lieu de `3`, `_getIfListCopy` sautait inconditionnellement à l'instruction `0x7ffc267b6091`, ignorant `en1` sans le moindre log d'erreur !
|
||||
- **Filtre 2 : Le Contrôle de Médium `SIOCGIFMEDIA` (`0xc02c6938`)** :
|
||||
```assembly
|
||||
0x7ffc267b6002: movl -0xc0(%rbp), %eax ; eax = ifmr.ifm_current
|
||||
0x7ffc267b6008: movl $0xe0, %ecx ; IFM_NMASK (0xe0)
|
||||
0x7ffc267b600d: andl %ecx, %eax ; type = ifmr.ifm_current & 0xe0
|
||||
0x7ffc267b600f: cmpl $0x80, %eax ; 0x80 == IFM_IEEE80211 !
|
||||
0x7ffc267b6022: jne 0x7ffc267b6091 ; Si != 0x80 -> REJET IMMÉDIAT !
|
||||
```
|
||||
* Sur notre interface, `ifm_current` renvoyait `0x20` (`IFM_ETHER`).
|
||||
* `(0x20 & 0xe0) != 0x80` provoquait également l'expulsion directe d'`en1`.
|
||||
2. **Origine Noyau de `ift_subfamily` et `ifm_current` dans Skywalk (`BootKernelExtensions.kc`)** :
|
||||
- Dans `IOSkywalkEthernetInterface::initRegistrationInfo` (`0xffffff8002b108e2`) :
|
||||
```assembly
|
||||
0xffffff8002b10958: mov dword ptr [rbx + 0x08], ecx ; family = 2 (ETHERNET)
|
||||
0xffffff8002b1095e: call qword ptr [r12 + 0x9b8] ; Slot 0x9b8 = getInterfaceSubFamily()
|
||||
0xffffff8002b10966: mov dword ptr [rbx + 0x0c], eax ; subfamily = 0 (par défaut !)
|
||||
0xffffff8002b10969: mov dword ptr [rbx + 0x24], 0x22 ; active medium = 0x22 (Ethernet)
|
||||
0xffffff8002b10985: mov dword ptr [rbx + 0x28], ecx ; current medium = 0x20 (Ethernet)
|
||||
```
|
||||
- Dans `registerNetworkInterfaceWithLogicalLink` (`0xffffff8002b0a204`) :
|
||||
```assembly
|
||||
0xffffff8002b0a2a9: call memcpy ; memcpy(priv->regInfo, fSkywalkRegInfo, 0x108)
|
||||
```
|
||||
- Le noyau copie fidèlement les `0x108` octets de `fSkywalkRegInfo` dans la structure interne `priv->regInfo`.
|
||||
- Lorsque `IOSkywalkNetworkBSDClient::start` enregistre le client BSD, `IOSkywalkEthernetInterface::initBSDInterfaceParameters` lit `slot 0x9a8` (`getInterfaceSubFamily`), qui renvoie la valeur de `priv->regInfo + 0x0c`.
|
||||
- Si `fSkywalkRegInfo + 0x0c` n'est pas explicitement configuré à `3` (`IFRTYPE_SUBFAMILY_WIFI`), BSD initialise `en1` avec un sous-type nul (`0`).
|
||||
* **Résolutions Techniques Appliquées dans `QualcommWifi.cpp`** :
|
||||
1. **Injection Directe de `IFRTYPE_SUBFAMILY_WIFI = 3` dans `fSkywalkRegInfo`** :
|
||||
- Immédiatement après l'appel à `initRegistrationInfo` (substep 8.1) :
|
||||
```cpp
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x0c) = 3; // IFRTYPE_SUBFAMILY_WIFI = 3
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x24) = 0x80; // active medium: kIOMediumIEEE80211Auto
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x28) = 0x80; // current medium: kIOMediumIEEE80211Auto
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x48) = 1500; // MTU
|
||||
*(uint32_t*)(fSkywalkRegInfo + 0x4c) = 1500; // Max MTU
|
||||
```
|
||||
2. **Mise à Jour de Sécurité des Structures Internes Skywalk (`priv` & `struct ifmedia`)** :
|
||||
- Immédiatement après `registerEthernetInterface` (substep 8.4) et après `registerService()` (substep 8.5) :
|
||||
```cpp
|
||||
uint8_t *priv = *(uint8_t **)((uint8_t *)fSkywalkInterface + 0xc0);
|
||||
if (priv) {
|
||||
uint8_t *regInfo = *(uint8_t **)priv;
|
||||
if (regInfo) {
|
||||
*(uint32_t *)(regInfo + 0x0c) = 3; // IFRTYPE_SUBFAMILY_WIFI
|
||||
*(uint32_t *)(regInfo + 0x24) = 0x80; // kIOMediumIEEE80211Auto
|
||||
*(uint32_t *)(regInfo + 0x28) = 0x80; // kIOMediumIEEE80211Auto
|
||||
}
|
||||
*(uint32_t *)(priv + 0x30) = 0x3; // ifm_status = IFM_AVALID | IFM_ACTIVE (0x1 | 0x2)
|
||||
*(uint32_t *)(priv + 0x34) = 0x80; // ifm_current = kIOMediumIEEE80211Auto (0x80)
|
||||
*(uint32_t *)(priv + 0x38) = 0x80; // ifm_active = kIOMediumIEEE80211Auto (0x80)
|
||||
}
|
||||
```
|
||||
3. **Purification du Dictionnaire de Médiums (`createMediumTables`)** :
|
||||
- Restriction exclusive au médium `kIOMediumIEEE80211Auto` à 1.2 Gbps (sans résidu Ethernet) pour garantir que `getMediaList` et `selectMedium` ne sélectionnent que des médiums conformes `IFM_IEEE80211`.
|
||||
4. **Validation Binaire & Déploiement** :
|
||||
- Compilation `Release` réussie sans erreur (`./build_wifi.sh`).
|
||||
- Validation des symboles et dépendances réussie à 100% via `kmutil libraries`.
|
||||
- Kext déployé sur l'EFI : `/Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext` (MD5: `918e6727043a53bbe4825671f428ab5c`).
|
||||
Reference in new issue
Block a user