Jahr-2038-Problem

Aus besserwiki.de
Eine animierte Darstellung des Fehlers in Aktion. Der Überlauffehler wird am 19. Januar 2038 um 03:14:08 Uhr auftreten.

Das Jahr-2038-Problem (auch bekannt als Y2038, Y2K38, die Epochalypse oder der Friday 13th Bug) ist ein Zeitformatierungsfehler in Computersystemen, die Zeiten nach 03:14:07 UTC am 19. Januar 2038 darstellen.

Das Problem besteht in Systemen, die die Unix-Zeit messen - die Anzahl der seit der Unix-Epoche (00:00:00 UTC am 1. Januar 1970) verstrichenen Sekunden - und sie in einer vorzeichenbehafteten 32-Bit-Ganzzahl speichern. Der Datentyp ist nur in der Lage, ganze Zahlen zwischen -(231) und 231 - 1 darzustellen, was bedeutet, dass die späteste Zeit, die korrekt kodiert werden kann, 231 - 1 Sekunden nach der Epoche (03:14:07 UTC am 19. Januar 2038) ist. Der Versuch, zur nächsten Sekunde (03:14:08) zu erhöhen, führt zu einem Überlauf der Ganzzahl und setzt ihren Wert auf -(231), was von den Systemen als 231 Sekunden vor Epoche (20:45:52 UTC am 13. Dezember 1901) interpretiert wird. Das Problem ist ähnlich gelagert wie das Jahr-2000-Problem.

Computersysteme, die die Zeit für kritische Berechnungen verwenden, können auf fatale Fehler stoßen, wenn das Y2038-Problem nicht angegangen wird. Einige Anwendungen, die zukünftige Daten verwenden, sind bereits auf den Fehler gestoßen. Am anfälligsten sind Systeme, die selten oder nie aktualisiert werden, wie ältere und eingebettete Systeme. Es gibt keine allgemeingültige Lösung für das Problem, obwohl viele moderne Systeme aufgerüstet wurden, um die Unix-Zeit mit vorzeichenbehafteten 64-Bit-Ganzzahlen zu messen, die 292 Milliarden Jahre lang nicht überlaufen werden.

Darstellung des Jahr-2038-Problems:
1.: Zeitdarstellung im Binärsystem
2.: die dazugehörige Dezimalzahl
3.: Fehlerhafte Darstellung der Zeit
4.: Korrekte Zeitangabe

Ursache

Viele Computersysteme messen Zeit und Datum als Unix-Zeit, einem internationalen Standard für die digitale Zeitmessung. Die Unix-Zeit ist definiert als die Anzahl der Sekunden, die seit 00:00:00 UTC am 1. Januar 1970 (ein willkürlich gewählter Zeitpunkt) verstrichen sind, was auch als Unix-Epoche bezeichnet wird.

Die Unix-Zeit wurde in der Vergangenheit als vorzeichenbehaftete 32-Bit-Ganzzahl kodiert, ein Datentyp, der aus 32 binären Ziffern (Bits) besteht, die einen ganzzahligen Wert darstellen, wobei "vorzeichenbehaftet" bedeutet, dass ein Bit für das Vorzeichen (+/-) reserviert ist. Eine 32-Bit-Ganzzahl mit Vorzeichen kann also nur Ganzzahlwerte von -(231) bis einschließlich 231 - 1 darstellen. Wenn eine 32-Bit-Ganzzahl mit Vorzeichen zur Speicherung der Unix-Zeit verwendet wird, ist die späteste Zeit, die gespeichert werden kann, 231 - 1 (2.147.483.647) Sekunden nach der Epoche, d. h. 03:14:07 am Dienstag, 19. Januar 2038. Systeme, die versuchen, diesen Wert um eine weitere Sekunde auf 231 Sekunden nach der Epoche (03:14:08) zu erhöhen, erleiden einen Integer-Überlauf, wobei das Vorzeichenbit versehentlich umgedreht wird, um eine negative Zahl anzuzeigen. Dadurch ändert sich der Integer-Wert auf -(231), d. h. 231 Sekunden vor der Epoche und nicht nach der Epoche, was die Systeme als 20:45:52 am Freitag, den 13. Dezember 1901 interpretieren werden. Von hier an zählen die Systeme weiter aufwärts, gegen Null, und dann wieder aufwärts durch die positiven ganzen Zahlen. Da viele Computersysteme Zeitberechnungen verwenden, um kritische Funktionen auszuführen, kann der Fehler zu fatalen Fehlern führen.

Der Zufall will es, dass das Datum, auf das die anfälligen Systeme zurückgesetzt werden, ein Freitag, der 13. ist, der in der westlichen Kultur als Unglückstag gilt.

Ohne Gegenmaßnahmen könnten die wirtschaftlichen Auswirkungen unter Umständen schädlich sein, zumal im Banken- und Versicherungsumfeld Unix-Systeme neben Mainframes zur Standardausstattung gehören. Neben den Unix-Servern arbeiten viele eingebettete Systeme mit Unix-artigen Betriebssystemen, deren Einsatzzeit oft ein Vielfaches von Desktop- und Serversystemen beträgt (z. B. Router und elektronische Messgeräte). Eine zumindest verzögerte, auf Dauer aber notwendige Anpassung bzw. Modernisierung entsprechender Rechnersysteme in Unternehmen und Institutionen in heutiger Zeit könnte die Ausfallwahrscheinlichkeit senken.

Anfällige Systeme

Jedes System, das Datenstrukturen mit 32-Bit-Zeitdarstellung verwendet, ist anfällig für Fehler. Es ist praktisch unmöglich, eine vollständige Liste dieser Datenstrukturen zu erstellen, aber es gibt bekannte Datenstrukturen, die das Unix-Zeitproblem haben:

  • Dateisysteme (viele Dateisysteme verwenden nur 32 Bit zur Darstellung von Zeiten in Inodes)
  • Binäre Dateiformate (die 32-Bit-Zeitfelder verwenden)
  • Datenbanken (die 32-Bit-Zeitfelder haben)
  • Datenbankabfragesprachen, wie SQL, die UNIX_TIMESTAMP()-ähnliche Befehle haben

Eingebettete Systeme

Eingebettete Systeme, die Datumsangaben entweder für Berechnungen oder für die Diagnoseprotokollierung verwenden, sind am ehesten von dem Y2038-Problem betroffen. Trotz des modernen 18- bis 24-monatigen Generationswechsels in der Computersystemtechnologie sind eingebettete Systeme so konzipiert, dass sie die Lebensdauer der Maschine überdauern, in der sie eine Komponente sind. Es ist denkbar, dass einige dieser Systeme auch im Jahr 2038 noch im Einsatz sind. Es kann unpraktisch oder in einigen Fällen unmöglich sein, die Software dieser Systeme zu aktualisieren, so dass sie letztendlich ersetzt werden müssen, wenn die 32-Bit-Beschränkungen behoben werden sollen.

In vielen Verkehrssystemen, vom Flugzeug bis zum Auto, werden eingebettete Systeme in großem Umfang eingesetzt. In Automobilen kann dies das Antiblockiersystem (ABS), die elektronische Stabilitätskontrolle (ESC/ESP), die Antriebsschlupfregelung (TCS) und der automatische Allradantrieb sein; in Flugzeugen können Trägheitsnavigationssysteme und GPS-Empfänger zum Einsatz kommen. Ein weiterer wichtiger Einsatzbereich eingebetteter Systeme sind Kommunikationsgeräte wie Mobiltelefone und internetfähige Geräte (z. B. Router, drahtlose Zugangspunkte, IP-Kameras), die auf die Speicherung einer genauen Uhrzeit und eines genauen Datums angewiesen sind und zunehmend auf Unix-ähnlichen Betriebssystemen basieren. Das Y2038-Problem führt beispielsweise dazu, dass einige Geräte mit 32-Bit-Android abstürzen und nicht neu gestartet werden können, wenn die Uhrzeit auf dieses Datum geändert wird.

Dies bedeutet jedoch nicht, dass alle eingebetteten Systeme von dem Y2038-Problem betroffen sind, da viele dieser Systeme keinen Zugriff auf das Datum benötigen. Bei den Systemen, die nur die Differenz zwischen Zeiten/Daten und nicht die absoluten Zeiten/Daten erfassen, wird es aufgrund der Art der Berechnung keine größeren Probleme geben. Dies ist der Fall bei Kfz-Diagnosesystemen, die auf gesetzlichen Normen wie der CARB (California Air Resources Board) basieren.

Frühe Probleme

Im Mai 2006 tauchten Berichte über ein frühes Auftreten des Y2038-Problems in der AOLserver-Software auf. Die Software wurde mit einem Trick entwickelt, um eine Datenbankanforderung zu behandeln, die "niemals" eine Zeitüberschreitung verursachen sollte. Anstatt diesen Sonderfall speziell zu behandeln, wurde im ursprünglichen Entwurf einfach ein beliebiges Zeitüberschreitungsdatum in der Zukunft festgelegt. Die Standardkonfiguration des Servers sah vor, dass die Anfrage nach einer Milliarde Sekunden ablaufen sollte. Eine Milliarde Sekunden (etwas mehr als 31 Jahre, 251 Tage, 1 Stunde, 46 Minuten und 40 Sekunden) nach 01:27:28 UTC am 13. Mai 2006 liegt jenseits des Stichtags 2038. Nach dieser Zeit lief die Zeitüberschreitungsberechnung also über und lieferte ein Datum, das eigentlich in der Vergangenheit lag, was zum Absturz der Software führte. Als das Problem entdeckt wurde, mussten die AOLServer-Betreiber die Konfigurationsdatei bearbeiten und die Zeitüberschreitung auf einen niedrigeren Wert setzen.

Spieler von Spielen oder Anwendungen, die so programmiert sind, dass sie Wartezeiten einführen, stoßen auf dieses Problem, wenn sie versuchen, die Wartezeit zu umgehen, indem sie das Datum auf ihren Geräten auf ein Datum nach dem 19. Januar 2038 einstellen, was jedoch nicht möglich ist, da ein 32-Bit-Unix-Zeitformat verwendet wird.

Lösungen

Es gibt keine universelle Lösung für das Jahr 2038-Problem. In der Sprache C zum Beispiel würde jede Änderung der Definition des Datentyps time_t zu Problemen mit der Code-Kompatibilität in jeder Anwendung führen, in der die Darstellung von Datum und Uhrzeit von der Art der vorzeichenbehafteten 32-Bit-Ganzzahl time_t abhängt. Die Änderung von time_t in eine 32-Bit-Ganzzahl ohne Vorzeichen, die den Bereich auf 2106 (genauer gesagt 06:28:15 UTC am Sonntag, 7. Februar 2106) erweitern würde, würde sich beispielsweise negativ auf Programme auswirken, die Daten vor 1970 speichern, abrufen oder bearbeiten, da solche Daten durch negative Zahlen dargestellt werden. Die Erhöhung der Größe des time_t-Typs auf 64 Bit in einem bestehenden System würde zu inkompatiblen Änderungen am Layout von Strukturen und der binären Schnittstelle von Funktionen führen.

Die meisten Betriebssysteme, die für 64-Bit-Hardware ausgelegt sind, verwenden bereits vorzeichenbehaftete 64-Bit-Time_t-Ganzzahlen. Die Verwendung eines vorzeichenbehafteten 64-Bit-Wertes führt ein neues umlaufendes Datum ein, das mehr als zwanzigmal so alt ist wie das geschätzte Alter des Universums: etwa 292 Milliarden Jahre in der Zukunft. Die Möglichkeit, Datumsberechnungen durchzuführen, wird dadurch eingeschränkt, dass tm_year einen vorzeichenbehafteten 32-Bit-Ganzzahlwert verwendet, der bei 1900 für das Jahr beginnt. Dadurch ist das Jahr auf maximal 2.147.485.547 (2.147.483.647 + 1900) begrenzt.

Es wurden alternative Vorschläge gemacht (von denen einige bereits verwendet werden), wie z. B. die Speicherung von Millisekunden oder Mikrosekunden seit einer Epoche (typischerweise entweder der 1. Januar 1970 oder der 1. Januar 2000) in einer vorzeichenbehafteten 64-Bit-Ganzzahl, was einen Mindestbereich von 300.000 Jahren bei Mikrosekundenauflösung ergibt. Insbesondere die Verwendung von 64-Bit-Long-Integers in Java zur Darstellung der Zeit als "Millisekunden seit dem 1. Januar 1970" wird für die nächsten 292 Millionen Jahre korrekt funktionieren. Andere Vorschläge für neue Zeitdarstellungen bieten unterschiedliche Genauigkeiten, Bereiche und Größen (fast immer breiter als 32 Bit) und lösen auch andere damit verbundene Probleme, wie die Behandlung von Schaltsekunden. TAI64 ist eine Implementierung des TAI-Standards (International Atomic Time), des aktuellen internationalen Echtzeitstandards für die Definition einer Sekunde und eines Bezugsrahmens.

Implementierte Lösungen

  • Ab Ruby Version 1.9.2 ist der Fehler mit dem Jahr 2038 behoben.
  • Ab NetBSD Version 6.0 (veröffentlicht im Oktober 2012) verwendet das NetBSD-Betriebssystem eine 64-Bit time_t sowohl für 32-Bit- als auch für 64-Bit-Architekturen. Anwendungen, die für eine ältere NetBSD-Version mit 32-Bit time_t kompiliert wurden, werden über eine Binärkompatibilitätsschicht unterstützt, aber solche älteren Anwendungen leiden immer noch unter dem Y2038-Problem.
  • OpenBSD seit Version 5.5, die im Mai 2014 veröffentlicht wurde, verwendet ebenfalls eine 64-Bit time_t sowohl für 32-Bit- als auch für 64-Bit-Architekturen. Im Gegensatz zu NetBSD gibt es keine binäre Kompatibilitätsschicht. Daher können Anwendungen, die eine 32-Bit time_t erwarten, und Anwendungen, die etwas anderes als time_t zum Speichern von Zeitwerten verwenden, nicht funktionieren.
  • Linux verwendete ursprünglich eine 64-Bit time_t nur für 64-Bit-Architekturen; die reine 32-Bit ABI wurde aus Gründen der Abwärtskompatibilität nicht geändert. Ab Version 5.6 von 2020 wird 64-Bit time_t auch auf 32-Bit-Architekturen unterstützt. Dies wurde vor allem für eingebettete Linux-Systeme eingeführt.
  • FreeBSD verwendet 64-Bit time_t für alle 32-Bit- und 64-Bit-Architekturen mit Ausnahme von 32-Bit i386, das stattdessen signierte 32-Bit time_t verwendet.
  • Die x32 ABI für Linux (die eine Umgebung für Programme mit 32-Bit-Adressen definiert, aber den Prozessor im 64-Bit-Modus betreibt) verwendet eine 64-Bit time_t. Da es sich um eine neue Umgebung handelt, waren keine besonderen Kompatibilitätsvorkehrungen erforderlich.
  • Network File System Version 4 hat seine Zeitfelder seit Dezember 2000 als struct nfstime4 {int64_t seconds; uint32_t nseconds;} definiert. Werte größer als Null für das Sekundenfeld bezeichnen Daten nach der 0-Stunde, dem 1. Januar 1970. Werte kleiner als Null für das Sekundenfeld bezeichnen Daten vor der 0-Stunde, 1. Januar 1970. In beiden Fällen ist für die endgültige Zeitdarstellung das Feld nseconds (Nanosekunden) zum Sekundenfeld hinzuzufügen.
  • Während die nativen APIs von OpenVMS Zeitstempel bis zum 31. Juli 31086 unterstützen können, verwendet die C-Laufzeitbibliothek (CRTL) 32-Bit-Ganzzahlen für time_t. Als Teil der Arbeiten zur Jahr-2000-Fähigkeit, die 1998 durchgeführt wurden, wurde die CRTL modifiziert, um vorzeichenlose 32-Bit-Ganzzahlen zur Darstellung der Zeit zu verwenden, wodurch der Bereich von time_t bis zum 7. Februar 2106 erweitert wurde.
  • Beginnend mit Telegram Version 8.0.1 (für Android und iOS), wurde in Version 3.1.0 (für Windows) von int32 auf int64 umgestellt.
  • Ab MySQL 8.0.28 verarbeiten die Funktionen FROM_UNIXTIME(), UNIX_TIMESTAMP() und CONVERT_TZ() 64-Bit-Werte auf Plattformen, die sie unterstützen. Dazu gehören 64-Bit-Versionen von Linux, MacOS und Windows. In relationalen Datenbankversionen vor August 2021 geben integrierte Funktionen wie UNIX_TIMESTAMP() nach 03:14:07 UTC am 19. Januar 2038 0 zurück.

Beispiel

Ein Beispiel für Jahr-2038-Fehler ist die Gültigkeitsprüfung per Zeitstempel: hierzu wird beim Beginn eines Vorganges die aktuelle Zeit gespeichert. Mit dieser kann sichergestellt werden, dass bis zum Abschluss des Vorgangs nicht mehr Zeit verstreicht als vorgegeben (beispielsweise die automatische Abmeldung beim Onlinebanking nach wenigen Minuten zur Missbrauchsvermeidung). Springt innerhalb einer solchen Frist der vom System angegebene Zeitstempel auf das Jahr 1901, so ist die Differenz fortan immer negativ. Erwartet das Programm nun aber eine positive Zahl mit einer Mindestgröße (z. B. 5 Minuten nach Beginn des Vorganges), wartet es vergeblich darauf, dass die Zahl positiv wird – die Zahl bleibt somit immer kleiner als der Zielwert von beispielsweise 5 Minuten. Das kann zu unerwünscht lange offen bleibenden Sicherheitszugängen führen oder auch zu Endlosschleifen, was sich für den Endbenutzer wie ein Nichtreagieren des Programms äußern kann.