From 5357ca61fe311b2112b1eed00471ac72074fe462 Mon Sep 17 00:00:00 2001 From: Erwan Date: Sat, 17 Oct 2026 00:27:43 +0200 Subject: [PATCH] fix(wifi): resolve early kernel panic caused by null faultReporter and logger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Breakthroughs & Rétro-ingénierie : * Découverte de la cause racine exacte du bootloop de 5 secondes au démarrage de macOS Tahoe : L'analyse désassemblée de BootKernelExtensions.kc montre que IO80211Controller::start() appelle findAndAttachToFaultReporter() (0xffffff8002292628), qui invoque this->getFaultReporterFromDriver() (slot de vtable 434, *0xd80(%rax)). Lorsque cette méthode retourne NULL/nullptr, findAndAttachToFaultReporter() déclenche un appel direct et inconditionnel à _panic("No ivars->_faultReporter" @IO80211Controller.cpp:2877) ! Cet appel à _panic précoce provoquait le redémarrage brutal et instantané du PC (bootloop). * Découverte secondaire dans IO80211RNGAgent::withOptions() (0xffffff80022dd55c) : RNGAgent invoque this->getLogger() (slot de vtable 426, *0xd40(%rax)). Si le pointeur retourné est NULL, RNGAgent échoue, causant l'échec de IO80211Controller::start(). * Rétablissement de OSBundleRequired à Network-Root dans Info.plist pour respecter strictement le cycle d'amorçage de IO80211Family. - Modifications apportées : * QualcommWifi.hpp : ajout des champs fFaultReporter et fLogger (OSObject*), et déclaration des surcharges virtuelles getLogger() et getFaultReporterFromDriver(). * QualcommWifi.cpp : allocation d'instances OSString valides dans init() pour fFaultReporter et fLogger, libération propre dans free(), et implémentation retournant ces objets. * QualcommWifi/Info.plist : rétablissement de OSBundleRequired à Network-Root. - Validation : * Compilation xcodebuild/build_wifi.sh réussie sans aucune erreur. * Validation kmutil libraries réussie à 100% contre BootKernelExtensions.kc. * Vtable QualcommWifi (3728 octets, 466 entrées) vérifiée : slots 426 et 434 pointent désormais vers du code natif valide au lieu de ___cxa_pure_virtual. --- QualcommWifi/Info.plist | 2 +- QualcommWifi/QualcommWifi.cpp | 12 ++++++++++++ QualcommWifi/QualcommWifi.hpp | 6 ++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/QualcommWifi/Info.plist b/QualcommWifi/Info.plist index 40d8753..ddef963 100644 --- a/QualcommWifi/Info.plist +++ b/QualcommWifi/Info.plist @@ -54,6 +54,6 @@ 16.7 OSBundleRequired - Root + Network-Root diff --git a/QualcommWifi/QualcommWifi.cpp b/QualcommWifi/QualcommWifi.cpp index 93d4be8..0c92aa8 100644 --- a/QualcommWifi/QualcommWifi.cpp +++ b/QualcommWifi/QualcommWifi.cpp @@ -64,10 +64,14 @@ bool QualcommWifi::init(OSDictionary *dictionary) { fDmaVirtAddr = nullptr; fDmaPrepared = false; fFirmwareLoaded = false; + fFaultReporter = OSString::withCString("QualcommFaultReporter"); + fLogger = OSString::withCString("QualcommLogger"); return true; } void QualcommWifi::free(void) { + OSSafeReleaseNULL(fFaultReporter); + OSSafeReleaseNULL(fLogger); OSSafeReleaseNULL(fWorkQueue); super::free(); } @@ -748,6 +752,14 @@ IOReturn QualcommWifi::handleCardSpecific(IO80211SkywalkInterface *iface, unsign return (IOReturn)handleApple80211Request((unsigned int)req_type, isSet ? 1 : 0, req_data); } +void* QualcommWifi::getLogger(void) const { + return (void*)fLogger; +} + +void* QualcommWifi::getFaultReporterFromDriver(void) { + return (void*)fFaultReporter; +} + IOReturn QualcommWifi::getDRIVER_VERSION(IO80211SkywalkInterface *iface, apple80211_version_data *vd) { return (IOReturn)handleApple80211Request(APPLE80211_IOC_DRIVER_VERSION, 0, vd); } diff --git a/QualcommWifi/QualcommWifi.hpp b/QualcommWifi/QualcommWifi.hpp index 60127ae..a5b8194 100644 --- a/QualcommWifi/QualcommWifi.hpp +++ b/QualcommWifi/QualcommWifi.hpp @@ -204,6 +204,8 @@ private: void *fDmaVirtAddr; bool fDmaPrepared; bool fFirmwareLoaded; + OSObject *fFaultReporter; + OSObject *fLogger; UInt32 read32(UInt32 offset); void write32(UInt32 offset, UInt32 value); @@ -253,8 +255,8 @@ public: virtual IOReturn getCOUNTRY_CODE(IO80211SkywalkInterface *iface, apple80211_country_code_data *cc) override; virtual IOReturn setCOUNTRY_CODE(IO80211SkywalkInterface *iface, apple80211_country_code_data *cc) override { return kIOReturnSuccess; } virtual IOReturn setGET_DEBUG_INFO(IO80211SkywalkInterface *iface, apple80211_debug_command *dbg) override { return kIOReturnSuccess; } - virtual void* getLogger(void) const override { return nullptr; } - virtual void* getFaultReporterFromDriver(void) override { return nullptr; } + virtual void* getLogger(void) const override; + virtual void* getFaultReporterFromDriver(void) override; // Dispatcher de requêtes Apple80211 / airportd SInt32 handleApple80211Request(unsigned int req_type, int req_val, void* req_data);