Medium firefox UAF 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionUse-after-free in the Widget: Cocoa component
ComponentNetworking
Bug ClassUAF
Tracker2016164
Fix commitb8acb4e4256a (firefox) +33/-4
CISA KEVNot listed
CreditedSteven Michaud
Disclosed2026-04-21

Changed Functions

FunctionChangeNotes
if
netwerk/system/mac/nsNetworkLinkService.mm
modified

Files Changed

  • netwerk/system/mac/nsNetworkLinkService.mm
diff --git a/netwerk/system/mac/nsNetworkLinkService.mm b/netwerk/system/mac/nsNetworkLinkService.mm
index 18c829cc0d0..1c157acebdc 100644
--- a/netwerk/system/mac/nsNetworkLinkService.mm
+++ b/netwerk/system/mac/nsNetworkLinkService.mm
@@ -710,9 +710,26 @@ void nsNetworkLinkService::NetworkConfigChanged(SCDynamicStoreRef aStoreREf,
 
   bool ipConfigChanged = false;
   bool dnsConfigChanged = false;
+  bool skipOnIPConfigChanged = false;
   for (CFIndex i = 0; i < CFArrayGetCount(aChangedKeys); ++i) {
     CFStringRef key =
         static_cast<CFStringRef>(CFArrayGetValueAtIndex(aChangedKeys, i));
+    // Don't call OnIPConfigChanged() if aChangedKeys contains any EAPOL
+    // notifications. This works around a crash bug deep in macOS system
+    // code. Our observers should still get reachability notifications, so
+    // this shouldn't interfere with network functionality.
+    if (CFStringHasSuffix(key, CFSTR("EAPOL"))) {
+      CFIndex keyMaxLength =
+          CFStringGetMaximumSizeForEncoding(CFStringGetLength(key),
+                                            kCFStringEncodingUTF8) +
+          1;
+      char* keyBuffer = static_cast<char*>(moz_xmalloc(keyMaxLength));
+      keyBuffer[0] = 0;
+      CFStringGetCString(key, keyBuffer, keyMaxLength, kCFStringEncodingUTF8);
+      LOG(("Skipping OnIPConfigChanged() on changed key %s", keyBuffer));
+      free(keyBuffer);
+      skipOnIPConfigChanged = true;
+    }
     if (CFStringHasSuffix(key, kSCEntNetIPv4) ||
         CFStringHasSuffix(key, kSCEntNetIPv6)) {
       ipConfigChanged = true;
@@ -723,7 +740,7 @@ void nsNetworkLinkService::NetworkConfigChanged(SCDynamicStoreRef aStoreREf,
   }
 
   nsNetworkLinkService* service = static_cast<nsNetworkLinkService*>(aInfo);
-  if (ipConfigChanged) {
+  if (ipConfigChanged && !skipOnIPConfigChanged) {
     service->OnIPConfigChanged();
   }
 
@@ -802,7 +819,8 @@ nsresult nsNetworkLinkService::Init(void) {
       ::SCDynamicStoreCreate(nullptr, CFSTR("IPAndDNSChangeCallbackSCF"),
                              NetworkConfigChanged, &storeContext);
 
-  CFStringRef patterns[4] = {nullptr, nullptr, nullptr, nullptr};
+  CFStringRef patterns[6] = {nullptr, nullptr, nullptr,
+                             nullptr, nullptr, nullptr};
   OSStatus err = getErrorCodePtr(mStoreRef);
   if (err == noErr) {
     // This pattern is "State:/Network/Service/[^/]+/IPv4".
@@ -817,7 +835,16 @@ nsresult nsNetworkLinkService::Init(void) {
     // This pattern is "Setup:/Network/Service/[^/]+/DNS".
     patterns[3] = ::SCDynamicStoreKeyCreateNetworkServiceEntity(
         nullptr, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetDNS);
-    if (!patterns[0] || !patterns[1] || !patterns[2] || !patterns[3]) {
+    // We want to be able to ignore some groups of notifications that contain
+    // "EAPOL" keys. This works around a crash bug deep in macOS system code.
+    // This pattern is "State:/Network/Service/[^/]+/EAPOL".
+    patterns[4] = ::SCDynamicStoreKeyCreateNetworkServiceEntity(
+        nullptr, kSCDynamicStoreDomainState, kSCCompAnyRegex, CFSTR("EAPOL"));
+    // This pattern is "State:/Network/Interface/[^/]+/EAPOL".
+    patterns[5] = ::SCDynamicStoreKeyCreateNetworkInterfaceEntity(
+        nullptr, kSCDynamicStoreDomainState, kSCCompAnyRegex, CFSTR("EAPOL"));
+    if (!patterns[0] || !patterns[1] || !patterns[2] || !patterns[3] ||
+        !patterns[4] || !patterns[5]) {
       err = -1;
     }
   }
@@ -828,7 +855,7 @@ nsresult nsNetworkLinkService::Init(void) {
   // that match that pattern list, then create our run loop
   // source.
   if (err == noErr) {
-    patternList = ::CFArrayCreate(nullptr, (const void**)patterns, 4,
+    patternList = ::CFArrayCreate(nullptr, (const void**)patterns, 6,
                                   &kCFTypeArrayCallBacks);
     if (!patternList) {
       err = -1;
@@ -848,6 +875,8 @@ nsresult nsNetworkLinkService::Init(void) {
   CFReleaseSafe(patterns[1]);
   CFReleaseSafe(patterns[2]);
   CFReleaseSafe(patterns[3]);
+  CFReleaseSafe(patterns[4]);
+  CFReleaseSafe(patterns[5]);
   CFReleaseSafe(patternList);
 
   if (err != noErr) {
Loading diff…