~ / topics / Testing & Remediation
$man remediation-guide

Remediation Guide

In brief: You fix the Year 2038 problem by making every place that stores or moves a time value wide enough to go past 19 January 2038. That covers hardware clocks, the operating system, system libraries, programming languages, your own code, your databases, your files and your network messages. The only lasting fix is 64-bit time. Shortcuts such as "treat the number as unsigned" or "shift the starting date" can buy time, but they bring risks of their own. This page goes through the layers in order and explains which shortcuts are safe and which are not.

Risk level High for 32-bit embedded/OT estates; Medium for mixed enterprise estates; Low for fully 64-bit, current software
Status Kernel, libc and major distributions are fixed upstream; applications, data formats, protocols and fielded devices still vary
Last reviewed 2026-10-21

Overview

A time value is only as wide as the narrowest place it passes through. A 64-bit kernel cannot help if the application stores expires_at in a 32-bit INT column. A 64-bit column cannot help if a 32-bit sensor writes the value. Remediation therefore works layer by layer, bottom up. You fix each dependency before what sits on top of it, and you test each step (see Testing-and-Detection).

There are four broad strategies:

Strategy What it does New limit Verdict
64-bit migration Widen time_t and every stored copy to signed 64 bits ~292 billion years Preferred. It is the only permanent fix
Unsigned reinterpretation Read the same 32 bits as uint32_t 2106-02-07 06:28:15 UTC Acceptable for on-wire or on-disk formats you can't change, with care
Epoch shifting Count from a later epoch (e.g. 2000) in the same 32 bits Epoch + 68 years Dangerous: ambiguous data, breaks interoperability
Windowing Decide at read time which 136-year "window" a wrapped value belongs to Sliding Dangerous: guesses, and the guesses fail at the edges

Why the shortcuts are dangerous

Technical details: remediation by layer

1. Hardware

2. Operating system kernel

3. C library and ABI

# 1. Add flags globally (CMake toolchain / Autotools site config / Yocto distro)
CFLAGS="$CFLAGS -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64"
# 2. For Gnulib/Autoconf projects, make configure fail if 64-bit time isn't available
#    (bootstrap.conf: add 'year2038-recommended')       [15]
# 3. Rebuild the whole dependency closure; never mix time32/time64 objects
# 4. Verify: no 32-bit time imports left (scan-time32.sh from Testing-and-Detection)

4. Language runtimes

Runtime Typical remediation
C/C++ Use time_t, int64_t and std::chrono end to end. Fix %d/%ld format strings (use %jd with a cast to intmax_t). Remove (int) casts. See Lang-C-and-CPP
Java/JVM Instant/long milliseconds are safe. Look for int seconds and (int)(System.currentTimeMillis()/1000). See Lang-Java-and-JVM
Python On 32-bit builds, datetime.fromtimestamp() and utcfromtimestamp() call the platform C library and still overflow. The LWPCookieJar bug report has stayed open since 2009 [20]. See Lang-Python
PHP, Perl, Ruby Check the platform integer size and the date functions used. Ruby ≥ 1.9.2 uses a 64-bit internal representation [5]. See Lang-PHP, Lang-Perl-Ruby-and-Others
.NET, JS, Go, Rust Native types are 64-bit. The risk is in interop and serialization. See Lang-DotNet, Lang-JavaScript-and-TypeScript, Lang-Go-Rust-Swift

5. Application code

  1. Run the grep and static-analysis passes in Testing-and-Detection to build a defect list.
  2. Replace narrow types with time_t or int64_t. Keep intervals (durations) and instants (points in time) in separate types.
  3. Replace "forever" sentinels with explicit flags, and use saturating addition for now + timeout.
  4. Prefer CLOCK_MONOTONIC for timeouts, so that wall-clock jumps (including deliberate test jumps) cannot trigger them [2].
  5. Add regression tests that run with a faked clock and with future data. Make the build fail if sizeof(time_t) < 8: _Static_assert(sizeof(time_t) >= 8, "need 64-bit time_t");

6. Data and schema

7. File formats and file systems

8. Protocols

9. Vendor and supply chain

Affected versions / products

Layer Minimum "2038-capable" baseline (32-bit targets)
Linux kernel 5.6 (5.1 syscalls) [1][2]
glibc 2.34 with _TIME_BITS=64 [6]
musl 1.2.0 [7]
Debian 13 "trixie" on armel/armhf; not i386 [8][10]
Yocto 4.3 [12]
NetBSD / OpenBSD 6.0 / 5.5 [5]
MySQL TIMESTAMP no fix; migrate column type [16]

Risk & compliance notes

Remediation work needs an owner per layer: platform team (OS/libc), application owners, DBAs and procurement. Track the status of each asset using the triage matrix in Risk-Assessment-Checklist. Treat any use of unsigned reinterpretation, epoch shifting or windowing as a documented exception with a stated expiry date.

Detection & mitigation

Verify every fix with the techniques in Testing-and-Detection. A remediation counts as complete only when post-2038 clock tests, future-data tests and binary scans all pass.

See also

References

  1. Linux 5.6 Is The First Kernel For 32-Bit Systems Ready To Run Past Year 2038 — Phoronix, 2020-01-29 — 5.6 milestone; user space must also use 64-bit time.
  2. Need 32-bit Linux to run past 2038? When version 5.6 of the kernel pops, you're in for a treat — The Register, 2020-01-30 — Bergmann quotes; time64 syscalls since 5.1; unsigned/CLOCK_MONOTONIC for unchangeable interfaces.
  3. Approaching the kernel year-2038 end game — LWN, 2019-01-11 — _time32/_time64 syscalls, COMPAT_32BIT_TIME.
  4. System call conversion for year 2038 — LWN, 2015-05-05 — design of the kernel conversion.
  5. Year 2038 problem — Wikipedia — NetBSD 6.0, OpenBSD 5.5, Ruby 1.9.2, ext4 2446, XFS bigtime 2486, NFS details, with primary links.
  6. GNU C Library 2.34 released — LWN, 2021-08-01 — _TIME_BITS=64, LFS requirement, Linux 5.1 minimum.
  7. musl 1.2.0 released — musl mailing list (Openwall), 2020-02-21 — 64-bit time_t on 32-bit archs.
  8. ReleaseGoals/64bit-time — Debian Wiki — t64 renaming, dates, architectures, known risk areas.
  9. The perils of transition to 64-bit time_t — Michał Górny (Gentoo), 2024-09-28 — ABI mixing hazards and Gentoo's strategy.
  10. Debian looks forward to 2038 — LWN, 2023-07-17 — Langasek's plan; i386 exclusion debate.
  11. gmtime, _gmtime32, _gmtime64 — Microsoft Learn — _USE_32BIT_TIME_T warnings.
  12. Release 4.3 migration notes — Yocto Project docs — 64-bit time_t on 32-bit targets from 4.3.
  13. Austin Group issue 0001462: Require (at least) 64-bit time_t — accepted POSIX change.
  14. krb5 commit: Add y2038 documentation — MIT, 2017-05 — unsigned cast pattern valid to 2106.
  15. Avoiding the year 2038 problem — GNU Gnulib manual — year2038(-recommended), utmp caveat.
  16. The DATE, DATETIME, and TIMESTAMP Types — MySQL 8.0 Reference Manual — TIMESTAMP range.
  17. MySQL 8.0.28 Release Notes — Oracle — 64-bit Unix-time functions.
  18. MariaDB 11.5.1 Release Notes — MariaDB — TIMESTAMP to 2106.
  19. Curious tale of broken VPNs, the Year 2038, and certs that expired 100 years ago — The Register, 2024-02-09 — certificate date overflow in practice.
  20. Issue 5537: LWPCookieJar cannot handle cookies with expirations of 2038 or greater on 32-bit platforms — bugs.python.org — long-running runtime-level 2038 bug.
  21. Justin Mason, "first known instance of the Y2038 bug" — jmason.ie, 2006-07-20 — AOLserver one-billion-second timeout.
  22. OpenSSH Bug 3329 — openssh-bugs, 2021-07-02 — clamping certificate dates at INT_MAX for display.
  23. The NTP Era and Era Numbering — D. L. Mills, University of Delaware — era-number approach to NTP's 2036 wrap.
  24. Bug #6122 OpenSSL::PKCS7 verify — Ruby issue tracker, 2012 — not_after capped at 2038 on 32-bit Windows Ruby.
  25. File Times — Microsoft Learn — FILETIME definition.
  26. VDE-2025-007: WAGO: Year 2038 problem — CERT@VDE, 2025-04-15 (rev. 2026-08-07) — controller advisory, CVE-2025-0101, FW32 fix.
  27. VDE-2025-020: WAGO: Switches affected by year 2k38 problem — CERT@VDE, 2025-06-02 — CVE-2025-1235.
  28. ICSA-25-261-07 Dover Fueling Solutions ProGauge MagLink LX4 — CISA, 2025-09-18 — CVE-2025-55068 and fixed versions.
  29. ICSA-25-296-03 Veeder-Root TLS4B — CISA, 2025-10-23 — CVE-2025-55067, fix pending.
  30. XFS — Gentoo Wiki — bigtime upgrade with xfs_admin; default since xfsprogs 5.15.