~ / topics / Operating Systems
$man os-linux

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:

  1. the kernel, which keeps time internally and exposes it through system calls (clock_gettime, stat, utimensat, futex, ioctls and so on);
  2. the C library (glibc, musl, uClibc-ng, bionic), which defines time_t and wraps those system calls;
  3. 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]:

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

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]'

See also

References

  1. Pondering 2038 — LWN.net (Jonathan Corbet), 2013-08-14. Why Linux cannot copy OpenBSD's flag-day ABI break. The Gleixner and Stultz proposals.
  2. Making inode time stamps y2038 ready (RFC 00/32) — Arnd Bergmann via LWN, 2014-05-30. The first y2038 kernel series.
  3. Converting system calls to 64-bit time_t, part 1 — Arnd Bergmann via LWN, 2015-05-06. The compat-handler approach and __kernel_timespec.
  4. [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.
  5. Solving the Year 2038 problem in the Linux kernel — Deepa Dinamani, opensource.com, 2019-01-21. Flag-day Coccinelle patch merged June 2018.
  6. y2038: add time64 syscalls — Arnd Bergmann via LWN, 2019-01-10. Common syscall numbers across architectures, targeting 5.1.
  7. [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.
  8. 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.
  9. 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.
  10. ReleaseGoals/64bit-time — Debian Wiki. Architectures, exclusions, ~495 libraries, 2024-02-27 start, known issues.
  11. 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.
  12. libc-alpha thread on time64 and LFS defaults — sourceware/public-inbox. Concern about Autoconf/Gnulib defaults and i686/Wine/Steam (seen in search results).
  13. musl 1.2.0 released — musl list (Openwall), 2020-02-20. 64-bit time_t on all 32-bit archs.
  14. Debian 13 "trixie" release notes §2.2.6 — Debian and Debian 13 released — Debian News, 2025-08-09. i386 excluded. Rebuild third-party software.
  15. Ubuntu 24.04 LTS release notes — Canonical. armhf time_t transition and the rrdtool known issue.
  16. Changes/RetireARMv7 — Fedora Project Wiki. Fedora 36 is the last ARMv7 release.
  17. 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.
  18. Project:Toolchain/time64 migration — Gentoo Wiki (edited 2025-05-16). Migration plan, time64-prep, open TODOs.
  19. Gentoo Council meeting summary, 2024-10-13 — Gentoo. Decision on the t64 CHOST suffix.
  20. Release 4.3 (nanbield) migration guide — Yocto Project. 64-bit time_t on 32-bit targets, with an ABI break.
  21. MISC-TN-033: How to cope with Y2038 problem — DAVE Embedded Systems wiki. Test results on Yocto Scarthgap, PetaLinux and Buildroot. BR2_TIME_BITS_64 since 2023.11 (secondary source).
  22. [Buildroot] package/Makefile.in: year2038 makes time_t 64-bit for glibc toolchains — Buildroot list, 2022-03. Both macros needed. musl needs none.
  23. Toolchain build failure with BR2_TIME_BITS_64 — Buildroot GitLab issue #16. Known 2024 toolchain problems.
  24. [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).
  25. E2fsprogs release notes — e2fsprogs project. 1.46.4 (2021-08-18): 256-byte inode default and a warning for 128-byte inodes.
  26. Year 2038 problem — Wikipedia. Secondary source for the ext4 extended range (to 2446, needs inodes larger than 128 bytes).
  27. Considerations in adopting RHEL 9, Chapter 11: File systems and storage — Red Hat documentation. RHEL 9 mkfs.xfs defaults to bigtime and inobtcount; such file systems are not mountable on RHEL 8.