macOS bringt offenbar einen schwerwiegenden Netzwerkfehler mit, der nach ziemlich genau 49,7 Tagen ohne Neustart zuschlägt. Dann bricht die TCP/IP-Netzwerkfunktionalität teilweise zusammen – und nur ein Reboot hilft.
Unerklärliche Ausfälle nach knapp 50 Tagen Laufzeit
Wer einen Mac als Server oder serverähnliches System betreibt, bewegt sich ohnehin etwas abseits des von Apple vorgesehenen Einsatzes. Zwar basiert macOS auf Unix, das System ist aber nicht speziell auf unbeaufsichtigten 24/7-Betrieb ausgelegt und entsprechend aufwendig dafür zu konfigurieren.
Im Alltag starten die meisten von Euch den Mac mindestens alle paar Wochen neu. Bleibt ein Gerät aber exakt 49 Tage, 17 Stunden, 2 Minuten und 47 Sekunden ohne Neustart in Betrieb, versagen plötzlich zentrale Bestandteile des Systems: Der TCP/IP-Stack bricht teilweise zusammen, neue Netzwerkverbindungen funktionieren nicht mehr.
Auf diesen Fehler ist das Team von Photon gestoßen, das eine Flotte von Macs zur Überwachung der iMessage-Dienste einsetzt. Dort traten aus heiterem Himmel Fälle auf, in denen einzelne Rechner keine Netzwerkverbindungen mehr annahmen, während sie auf Ping-Anfragen weiterhin ordnungsgemäß reagierten.
Bestehende Verbindungen blieben aktiv, was die Fehlersuche deutlich erschwerte. Von außen wirkte alles in Ordnung, nur neue Verbindungen kamen nicht mehr zustande. Mangels anderer Optionen blieb dem Photon-Team zunächst nur der Neustart der betroffenen Macs – eine Notlösung, die Administrator:innen ungern akzeptieren, weil ein ungeklärtes Problem jederzeit erneut auftreten kann.
Fehlerquelle: Überlauf eines Zeitzählers im TCP-Stack
Als weitere Geräte in die Nähe der 49,7-Tage-Laufzeit kamen, richtete Photon Skripte ein, um die Vermutung zu überprüfen. Das Ergebnis: Erreicht ein Mac diesen Zeitpunkt, stellt er das Anlegen neuer Verbindungen einfach ohne jede Fehlermeldung ein.
Die Entwickler:innen suchten daraufhin gezielt nach einem Zusammenhang mit einem Netzwerk-Timer und wurden fündig: Der interne Zähler „tcp_now“ war der Auslöser. Er erfasst aus Sicht des TCP-Stacks die vergangene Zeit seit dem Systemstart in Millisekunden und ist als 32-Bit-Ganzzahl ohne Vorzeichen implementiert. Der Maximalwert beträgt 4.294.967.295 (2^32 − 1) Millisekunden, also 4.294.967 Sekunden – das entspricht etwa 49,7 Tagen.
Wie in den Standards vorgesehen, sammeln Betriebssysteme geschlossene TCP-Verbindungen ein und löschen sie nach kurzer Zeit; unter macOS nach 30 Sekunden. Versucht das System jedoch, solche inaktiven Verbindungen zu bereinigen, während tcp_now nahe an seinem Maximalwert liegt oder ihn erreicht (und sich aufgrund eines Fehlers im XNU-Kernel dort „festfährt“), wird jede Ablaufprüfung gegen diesen eingefrorenen Wert gerechnet. Das Ergebnis überläuft stets den 32-Bit-Bereich.
Die periodische Prüfung, ob eine geschlossene Verbindung gelöscht werden soll, liefert daher immer „nein“, weil der Vergleich durch den Überlauf mathematisch fehlschlägt. Der TCP-Stack füllt sich mit nicht freigegebenen, kurzlebigen Ports, bis schließlich keine Ports mehr verfügbar sind und der Netzwerkverkehr weitgehend zum Erliegen kommt. Wie schnell das passiert, hängt von der Netzlast ab, in Server- oder professionellen Umgebungen geht es jedoch sehr rasch.
Solche Probleme sind nicht neu: Ganzzahlüberläufe waren bereits die Ursache für den berüchtigten 49,7-Tage-Absturz von Windows 98 und stehen auch hinter dem anstehenden Jahr-2038-Problem.
Nur Neustart hilft vorerst – Apple-Kernel implementiert Standard falsch
Laut Photon gibt es aktuell nur eine wirksame Abhilfe: den betroffenen Mac neu starten. Das Team arbeitet nach eigenen Angaben an einer alternativen Lösung und hat den Fehler zudem als Ursache für einige diskutierte Probleme in den Apple-Supportforen identifiziert.
Die schon länger existierende RFC 7323 legt fest, was passieren soll, wenn die Zeitstempel-Uhr (tcp_now) ihr Limit erreicht. Der macOS-Kernel setzt diese Vorgabe jedoch fehlerhaft um. Es ist zu erwarten, dass Apple den Bug vergleichsweise zeitnah schließt – idealerweise deutlich vor Ablauf von 49,7 Tagen nach Eingang des Berichts.