Linux
In brief: 64-bit Linux has always used 64-bit time and is safe at the kernel level. 32-bit Linux, which is still common on ARM and MIPS devices, needed changes to the kernel, the C library and every program. The kernel finished its part in 2020 (Linux 5.6). The C libraries followed (musl 1.2.0 in 2020, glibc 2.34 in 2021). Debian and Ubuntu rebuilt their 32-bit ARM ports in 2024. Old 32-bit binaries, some file systems and the login-record files are still at risk.
| Risk level | Low (64-bit) · High (32-bit devices built before ~2024 or with old toolchains) |
| Status | Kernel fixed in 5.6. glibc opt-in since 2.34. musl default since 1.2.0. Debian/Ubuntu armhf fixed. i386 is deliberately left on 32-bit time |
| Last reviewed | 2026-10-21 |
2038 status at a glance
- At risk Confirmed32-bit glibc programs built without _TIME_BITS=64Even glibc 2.34+ keeps a 32-bit time_t by default on 32-bit platforms. 64-bit time is opt-in.Do: Rebuild with -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 (glibc 2.34+, kernel 5.1+). Rebuild all libraries that exchange time structures together.
- At risk Confirmed32-bit Linux with a kernel older than 5.6Kernels before 5.1 have no 64-bit time system calls for 32-bit programs, and 5.1–5.5 are incomplete.Do: Move to Linux 5.6 or later (or a vendor backport), then rebuild userland with 64-bit time.
- At risk ConfirmeduClibc-ng before 1.0.46No time64 support. uClibc-ng is common in older embedded and router SDKs.Do: Upgrade to 1.0.46+ with TIME64 enabled, on kernel 5.1+.
- At risk ConfirmedDebian 12 and earlier, Ubuntu 23.10 and earlier (32-bit ARM)armhf and armel used a 32-bit time_t until the 2024 transition.Do: Upgrade to Debian 13 or Ubuntu 24.04 LTS, and rebuild third-party armhf software.
- At risk ConfirmedDebian and Ubuntu i386Deliberately left on a 32-bit time_t so legacy binaries keep working.Do: Move workloads to amd64, and treat i386 only as a legacy-compatibility layer.
- At risk Confirmedmusl 1.1.24 and earlierThese versions have a 32-bit time_t on 32-bit platforms. Older Alpine, OpenWrt and embedded images inherit it.Do: Upgrade to musl 1.2.0 or later and rebuild.
- At risk ConfirmedLogin records (utmp, wtmp, lastlog) on glibc before 2.40These use a 32-bit seconds field even on x86-64. glibc 2.40 made it unsigned, which moves the limit to 2106.Do: Upgrade glibc and migrate tools off utmp/wtmp (for example to systemd-logind/wtmpdb).
- DependsBuildroot and Yocto 32-bit imagesYocto 4.3+ builds 32-bit targets with 64-bit time_t and ships a 32bit-time QA check. Buildroot glibc toolchains need BR2_TIME_BITS_64. musl toolchains need nothing.Do: Use Yocto 4.3+, or enable BR2_TIME_BITS_64, and run the QA checks.
Not affected or different deadline (2), and why
- Not affected64-bit Linux (kernel and C library)64-bit Linux has used a 64-bit time_t since those ports began. The kernel, glibc and musl all agree.Do: Still check file systems, login records and application data formats.
- Not affectedDebian 13 and Ubuntu 24.04+ on 32-bit ARMRebuilt in 2024–2025 with a 64-bit time_t, using the t64 library transition.Do: Rebuild any third-party armhf binaries. Debian warns of possible silent data loss otherwise.
Overview
On Linux, a program's view of time depends on three layers:
- the kernel, which keeps time internally and exposes it through system calls (
clock_gettime,stat,utimensat,futex, ioctls and so on); - the C library (glibc, musl, uClibc-ng, bionic), which defines
time_tand wraps those system calls; - userland: every library and application, plus their on-disk and on-wire formats.
On 64-bit architectures long is 64 bits, so time_t has been 64 bits since those ports began, and all three layers agree. On 32-bit architectures (i386, armel/armhf, 32-bit MIPS, PowerPC, and others) time_t was a 32-bit long. All three layers had to change. Linux also does not control its userspace the way the BSDs do, so it could not take OpenBSD's route of a single incompatible ABI flag day. This made the transition, in LWN's words, considerably more complicated [1].
Technical details
Kernel work (2014–2020)
The kernel effort was led by Arnd Bergmann (Linaro), working with many contributors, among them Deepa Dinamani in her Outreachy internship, Thomas Gleixner and John Stultz.
| Date | Milestone |
|---|---|
| 2013-08 | LWN's "Pondering 2038" sets out the options, including a proposal to make time_t unsigned [1]. |
| 2014-05-30 | Bergmann's RFC "Making inode time stamps y2038 ready" (32 patches) [2]. |
| 2015-05-06 | "Converting system calls to 64-bit time_t, part 1" proposes reusing the compat syscall handlers for 32-bit architectures [3]. |
| 2016 | Dinamani's VFS preparation series (vfs_time helpers) is merged for 4.7 [4]. |
| 2018-06 | Inode and iattr timestamps are converted treewide from timespec to timespec64. This was a flag-day patch generated with Coccinelle across more than 80 files [4][5]. |
| 2019 (Linux 5.1) | New time64 system calls for all 32-bit architectures, such as clock_gettime64, clock_settime64, utimensat_time64, futex_time64, ppoll_time64, pselect6_time64, recvmmsg_time64, semtimedop_time64, rt_sigtimedwait_time64 and timerfd_*_time64. They use the same syscall numbers on every architecture [6][7]. |
| 2020 (Linux 5.6) | Remaining drivers and file systems are converted, and the old time_t/timeval/timespec types are removed from kernel internals. Bergmann: "linux-5.6, or my backport of the patches to 5.4, should be the first release that can serve as a base for a 32-bit system designed to run beyond year 2038" [7]. |
| 2020 (Linux 5.10) | XFS gains the optional bigtime on-disk format, extending timestamps to July 2486 [8]. |
The 5.6 pull request lists caveats that still apply [7]:
- "All user space must be compiled with a 64-bit time_t". That requires musl ≥ 1.2 or glibc ≥ 2.32 together with kernel headers from 5.6 or later.
- Programs that make system calls directly, without going through libc, must switch to the time64 calls. This affects "most users of futex() and seccomp()" as well as language runtimes such as Go.
- Applications that carry private copies of kernel headers (
sound/asound.h,xfs/xfs_fs.h,linux/input.h,linux/timex.h) may need updating. - Some interfaces cannot change compatibly. They use
CLOCK_MONOTONICor an unsigned 32-bit timestamp instead, which moves the problem to 2106. The most important example isstruct input_event. - File-system limits are the same on 64-bit and 32-bit machines: "ext4 with small inodes, ext2, xfs … and ufs".
The kernel keeps the legacy 32-bit time syscalls for old binaries (CONFIG_COMPAT_32BIT_TIME). An old 32-bit binary running on a new kernel therefore still breaks in 2038. The kernel fix only protects programs that are rebuilt.
glibc
| glibc version | y2038 change |
|---|---|
| 2.31 (2020) | Time-related syscall wrappers try the new time64 syscalls first and fall back to the 32-bit ones. This can upset seccomp sandboxes that do not return -ENOSYS [9]. |
| 2.32 (2020) | New 32-bit ports such as ARC use 64-bit time from the start ("y2038 safe") [9]. The 5.6 pull request names 2.32 as the minimum for time64 userland [7]. |
| 2.34 (2021-08) | "Add support for 64-bit time_t on configurations like x86 where time_t is traditionally 32-bit … enabled with the _TIME_BITS preprocessor macro set to 64 and is only supported when LFS (_FILE_OFFSET_BITS=64) is also enabled … full support requires a minimum kernel version of 5.1." The 32-bit default is retained: "this default may change in future versions" [9]. |
| 2.35–2.38 | A series of y2038 bug fixes, for example "Program crashes if date beyond 2038" (#28880), "strftime %s returns -1 after 2038 on 32 bits systems" (#30053), and _TIME_BITS=64 with C++ (#28182) [9]. |
| 2.40 (2024) | Architectures that use a 32-bit seconds field in struct lastlog, struct utmp and struct utmpx (including i386 and x86-64) changed it from signed to unsigned, extending it to 2106. Applications "are still expected to migrate off" <utmp.h> [9]. |
Building against glibc on 32-bit:
# both macros are required; glibc rejects _TIME_BITS=64 without LFS
CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64"
The ABI hazard. _TIME_BITS changes the size of time_t and of every struct that contains one, but it does not change library sonames. If a library built with a 32-bit time_t exchanges a struct timespec with a program built with a 64-bit time_t, data is silently corrupted. That is why distributions had to rebuild in a coordinated way, not package by package [10][11]. GNU Autoconf and Gnulib have started enabling 64-bit time by default where it is available, with --disable-year2038 as the opt-out. A glibc maintainer warned that this endangers i686 ports that must stay ABI-compatible [12].
musl
musl 1.2.0 (announced 2020-02-20) "moves all 32-bit archs to 64-bit time_t, enabling them to represent times beyond January of 2038" [13]. Unlike glibc there is no opt-in macro: every 32-bit musl build from 1.2.0 onward uses 64-bit time. Code compiled against older musl is not ABI-compatible where it passes time_t-containing structs across library boundaries. Alpine, OpenWrt and many embedded distributions inherited the change.
Distributions
| Distribution | 32-bit time_t status | Notes |
|---|---|---|
| Debian | armel, armhf (and the non-release ports hppa, m68k, powerpc, sh4) moved to 64-bit time_t. i386 stays 32-bit. hurd-i386 is excluded |
Proposed 2023-05-16. The transition began 2024-02-27 with dpkg 1.22.5. About 495 library packages changed ABI, and affected libraries were renamed with a t64 suffix (libfoo → libfoot64). The wiki says it was settled by June 2024 [10]. Debian 13 "trixie" (released 2025-08-09): "All architectures other than i386 now use a 64-bit time_t ABI" [14]. |
| Ubuntu | armhf moved to 64-bit time_t in 24.04 LTS (April 2024) |
"Ubuntu 24.04 LTS solves the Year 2038 problem that existed on armhf. More than a thousand packages have been updated." Old rrdtool databases on armhf are incompatible [15]. |
| Fedora | No 32-bit primary architecture | ARMv7/armhfp dropped in Fedora 37, with Fedora 36 the last release [16]. i686 survives mainly as multilib for Wine and Steam, and maintainers have argued that a 64-bit time_t rebuild would break those 32-bit binaries [12]. No Fedora Change mandating 64-bit time_t on i686 was found (unverified as of 2026-10-21). |
| openSUSE | 64-bit primary | Tumbleweed and MicroOS stopped using /run/utmp, /var/log/wtmp and /var/log/lastlog in November 2023, replacing them with logind, wtmpdb and lastlog2 [17]. |
| Gentoo | 32-bit glibc profiles are being migrated | musl 1.2 entered the tree in 2020. glibc time64 was stabilised in April 2022. The October 2024 council decision adds a t64 suffix to CHOST (for example i686-pc-linux-gnut64) for migrated systems. The migration tool time64-prep moves old libraries to libt32. The migration TODO list was still open in May 2025 [18][19]. |
| Yocto Project | 64-bit time on 32-bit targets by default since 4.3 "Nanbield" (2023) | "Code on 32 bit platforms is now compiled with largefile support and 64 bit time_t, to avoid the Y2038 time overflow issue. This breaks the ABI" [20]. Scarthgap (5.0 LTS) carries this forward [21]. |
| Buildroot | BR2_TIME_BITS_64 option for glibc toolchains |
Passes -D_TIME_BITS=64. Reported as available since 2023.11 [21]. musl toolchains need no flag [22]. Some GCC builds failed with the option in 2024 [23]. uClibc-ng gained time64 support in 1.0.46/1.0.47 (2024) [24]. |
| Alpine, OpenWrt, Void-musl | 64-bit via musl ≥ 1.2 | Inherited from musl [13]. |
Remaining issues
| Area | Problem | Fix |
|---|---|---|
| ext2 / ext3, and ext4 with 128-byte inodes | Only 32-bit signed seconds on disk, so the range ends in 2038. ext4 with ≥256-byte inodes uses extra epoch bits and reaches the year 2446 [26]. | e2fsprogs 1.46.4 (2021-08-18) made 256-byte inodes the default for all non-Hurd file systems and warns when 128-byte inodes are created [25]. Check with tune2fs -l /dev/X \| grep "Inode size". A 128-byte file system has to be recreated, or migrated with tune2fs -I 256 where that is supported. |
| XFS | Classic format ends in January 2038. | bigtime (Linux 5.10+) runs to 2486. It was opt-in when introduced [8]. RHEL 9's mkfs.xfs enables it by default, and those file systems cannot be mounted on RHEL 8 [27]. See File-Systems for xfsprogs defaults on other distributions. Existing file systems can be upgraded offline with xfs_admin -O bigtime=1 (verify against your xfsprogs version). |
| utmp / wtmp / lastlog | struct utmp uses a 32-bit seconds field even on x86-64, for compatibility of the on-disk format. |
glibc 2.40 made it unsigned, which lasts to 2106 [9]. The long-term replacement is systemd-logind, wtmpdb and lastlog2 [17]. Debian's wiki lists utmp/wtmp changes for 32-bit programs as a known issue [10]. |
struct input_event |
Moved to unsigned 32-bit seconds, which ends in 2106 [7]. | n/a |
| Old 32-bit binaries | Proprietary or unrebuildable i386/armhf binaries keep a 32-bit time_t. |
Rebuild, isolate, or retire. Debian and Ubuntu deliberately keep i386 as 32-bit time for legacy software [14]. |
| Direct syscalls and seccomp | Runtimes that bypass libc, and seccomp filters that do not allow the *_time64 syscalls. |
Update the runtime and the filters [7][9]. |
| NFS, UFS, other file systems | Varies by on-disk format. | See File-Systems. |
Affected versions / products
| Component | Safe from | Not safe |
|---|---|---|
| Linux kernel (32-bit arch) | 5.6 (or Bergmann's 5.4 backport) [7] | < 5.1 has no time64 syscalls. 5.1–5.5 is incomplete |
| glibc (32-bit) | 2.34 with _TIME_BITS=64 [9] |
Any build without the flag |
| musl | 1.2.0 [13] | ≤ 1.1.24 |
| uClibc-ng | 1.0.46+ with TIME64 enabled, kernel ≥ 5.1 [24] | Earlier versions |
| Debian armhf/armel | 13 "trixie" [14] | 12 "bookworm" and earlier |
| Ubuntu armhf | 24.04 LTS [15] | 23.10 and earlier |
| Yocto (32-bit targets) | 4.3 Nanbield [20] | Earlier, unless configured otherwise |
| Any 64-bit Linux | Always (kernel and libc) | Still check file systems, utmp and application formats |
Risk & compliance notes
- Embedded fleets are the main exposure. Devices on Linux 4.x or earlier, glibc before 2.34 or musl before 1.2 cannot run past 2038 without a firmware update. See Devices-and-Embedded-Systems and OS-Embedded-and-RTOS.
- Silent data corruption is possible when time64 and time32 objects are mixed. Debian warns that third-party armhf software must be "recompiled/rebuilt, and checked for possibly silent data loss" [14].
- Inventory: kernel version, libc and version, the
_TIME_BITSsetting, file-system inode size and XFS feature flags, and any use ofutmp/wtmp.
Detection & mitigation
getconf LONG_BIT # 32 or 64
printf '#include <stdio.h>\n#include <time.h>\nint main(void){printf("%%zu\\n",sizeof(time_t));}\n' \
| ${CC:-cc} -x c - -o /tmp/tt && /tmp/tt # prints 8 if time_t is 64-bit
ldd --version | head -1 # glibc version
tune2fs -l /dev/sdXN | grep -i 'inode size'
xfs_info /mountpoint | grep -o 'bigtime=[01]'
- Rebuild 32-bit userland with
-D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64(glibc), or use musl ≥ 1.2. - Test by setting the clock past 2038 in a VM, or with
faketime '2038-01-19 03:14:00'. - See Testing-and-Detection and Remediation-Guide.
See also
- Year-2038-Problem · Operating-Systems · OS-Android · OS-Embedded-and-RTOS
- Lang-C-and-CPP · File-Systems · File-Formats-and-Protocols
- Year-2106-and-Beyond · Testing-and-Detection · Remediation-Guide
References
- Pondering 2038 — LWN.net (Jonathan Corbet), 2013-08-14. Why Linux cannot copy OpenBSD's flag-day ABI break. The Gleixner and Stultz proposals.
- Making inode time stamps y2038 ready (RFC 00/32) — Arnd Bergmann via LWN, 2014-05-30. The first y2038 kernel series.
- Converting system calls to 64-bit time_t, part 1 — Arnd Bergmann via LWN, 2015-05-06. The compat-handler approach and
__kernel_timespec. - [GIT PULL] y2038 changes for vfs — Arnd Bergmann, LKML, 2016 and [GIT PULL] vfs/y2038: inode timestamps conversion to timespec64 — LKML, 2018-06. Dinamani's Outreachy VFS work.
- Solving the Year 2038 problem in the Linux kernel — Deepa Dinamani, opensource.com, 2019-01-21. Flag-day Coccinelle patch merged June 2018.
- y2038: add time64 syscalls — Arnd Bergmann via LWN, 2019-01-10. Common syscall numbers across architectures, targeting 5.1.
- [GIT PULL] y2038: core, driver and file system changes — Arnd Bergmann, LKML, 2020-01-29. 5.6 readiness, caveats and remaining file systems. See also The Register, 2020-01-30.
- XFS File-System With Linux 5.10 Punts Year 2038 Problem To The Year 2486 — Phoronix, 2020-10-15.
bigtime, December 1901 to July 2486, not on by default. - glibc NEWS (mirror of glibc.git) — GNU C Library. Entries for 2.31, 2.32, 2.34, 2.36–2.38 bug lists, and 2.40 utmp.
- ReleaseGoals/64bit-time — Debian Wiki. Architectures, exclusions, ~495 libraries, 2024-02-27 start, known issues.
- Should be built with 64-bit time_t on 32-bit GNU architectures (dbus #465) — freedesktop.org GitLab. An example of the ABI hazard of
_TIME_BITS. - libc-alpha thread on time64 and LFS defaults — sourceware/public-inbox. Concern about Autoconf/Gnulib defaults and i686/Wine/Steam (seen in search results).
- musl 1.2.0 released — musl list (Openwall), 2020-02-20. 64-bit
time_ton all 32-bit archs. - Debian 13 "trixie" release notes §2.2.6 — Debian and Debian 13 released — Debian News, 2025-08-09. i386 excluded. Rebuild third-party software.
- Ubuntu 24.04 LTS release notes — Canonical. armhf time_t transition and the rrdtool known issue.
- Changes/RetireARMv7 — Fedora Project Wiki. Fedora 36 is the last ARMv7 release.
- Y2038: /run/utmp, /var/log/wtmp and /var/log/lastlog are gone — openSUSE MicroOS blog (Thorsten Kukuk), 2023-11-06. The wtmpdb, lastlog2 and logind replacements.
- Project:Toolchain/time64 migration — Gentoo Wiki (edited 2025-05-16). Migration plan,
time64-prep, open TODOs. - Gentoo Council meeting summary, 2024-10-13 — Gentoo. Decision on the
t64CHOST suffix. - Release 4.3 (nanbield) migration guide — Yocto Project. 64-bit
time_ton 32-bit targets, with an ABI break. - MISC-TN-033: How to cope with Y2038 problem — DAVE Embedded Systems wiki. Test results on Yocto Scarthgap, PetaLinux and Buildroot.
BR2_TIME_BITS_64since 2023.11 (secondary source). - [Buildroot] package/Makefile.in: year2038 makes time_t 64-bit for glibc toolchains — Buildroot list, 2022-03. Both macros needed. musl needs none.
- Toolchain build failure with BR2_TIME_BITS_64 — Buildroot GitLab issue #16. Known 2024 toolchain problems.
- [Buildroot] package/uclibc: update to 1.0.46 — Buildroot list, 2024-03 and uClibc-ng commit log (time64) — cgit. time64 for ARM, PowerPC, MIPS and others in 2024 (seen in search results).
- E2fsprogs release notes — e2fsprogs project. 1.46.4 (2021-08-18): 256-byte inode default and a warning for 128-byte inodes.
- Year 2038 problem — Wikipedia. Secondary source for the ext4 extended range (to 2446, needs inodes larger than 128 bytes).
- Considerations in adopting RHEL 9, Chapter 11: File systems and storage — Red Hat documentation. RHEL 9
mkfs.xfsdefaults to bigtime and inobtcount; such file systems are not mountable on RHEL 8.