Skip to content

Commit 23626e7

Browse files
fix: Update the Y2K38 guide
Since the Y2K38 issue is resolved in Scarthgap, update the guide to reflect the current state. Also, add explanation of how Yocto/OE ensures Y2K38 compliance, and expand guidance on ensuring third-party code is Y2K38-friendly. Signed-off-by: Telukula Jeevan Kumar Sahu <j-sahu@ti.com>
1 parent 649cff3 commit 23626e7

1 file changed

Lines changed: 138 additions & 32 deletions

File tree

Lines changed: 138 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,157 @@
1-
######################
2-
How to Fix Y2K38 Issue
3-
######################
1+
##########################
2+
How to Prevent Y2K38 Issue
3+
##########################
44

55
************************
66
What is the Y2K38 Issue?
77
************************
88

9-
The Y2K38 issue is a bug which prevents a date from exceeding 03:14:07 UTC on January 19, 2038, on 32-bit systems. This
10-
is because the structures used to store the date experience an integer overflow when the date is set beyond the mentioned
11-
one. This causes the system to crash.
9+
The Y2K38 issue is a time computing problem that prevents 32-bit systems from representing
10+
dates beyond 03:14:07 UTC on January 19, 2038. On 32-bit platforms, the Unix time is stored
11+
as a signed 32-bit integer (``time_t``) counting seconds since the Unix epoch
12+
(00:00:00 UTC on January 1, 1970). This integer overflows at 2,147,483,647 (0x7FFFFFFF),
13+
wrapping to a large negative value and causing the system to interpret the time as a date in 1901.
1214

1315
For more information, see: https://en.wikipedia.org/wiki/Year_2038_problem
1416

15-
There are new data structures that are used on 32-bit systems to store date/time in longer fields, thereby avoiding the
16-
overflow and the crash. However, since setting and displaying date/time uses multiple software components (such as the
17-
kernel, glibc etc), **all** code on a filesystem must be Y2K38-compliant (i.e. all code must be using the new data
18-
structures and functions) for the filesystem to be Y2K38-friendly. If any piece of software uses the older structures
19-
and functions, it makes the whole filesystem vulnerable.
17+
The fix requires updates at every layer of the software stack — kernel, C library (glibc),
18+
and all userspace applications. If any component is built without Y2K38 support, the entire
19+
system is vulnerable.
2020

21-
To understand how the problem was fixed in Scarthgap filesystem, refer:
22-
https://static.sched.com/hosted_files/osseu2024/8b/EOSS%20Vienna%202024%20-%20Surviving%20Y2038.pdf
21+
********************
22+
Y2K38 Issue Resolved
23+
********************
2324

24-
*******************************
25-
Building a Y2K38-friendly Image
26-
*******************************
25+
**The current SDK release is based on Scarthgap filesystem, which has the Y2K38 issue resolved.**
2726

28-
In SDK 9.3, TI's 32-bit platforms are still based on Kirkstone filesystem, which is NOT Y2K38-friendly. The Y2K38 issue
29-
is fixed in OE-core Scarthgap, on which the next release will be based.
27+
TI's 32-bit platforms (AM335x, AM437x) now use OE-core Scarthgap, which ships with all
28+
necessary fixes applied at every software layer. The filesystem images provided in this SDK
29+
are Y2K38-compliant out of the box.
3030

31-
Until then, if a Y2K38-friendly filesystem is required, obtain a :file:`tisdk-thinlinux-image` from the latest
32-
`cicd.scarthgap.x`:
31+
How Yocto/OpenEmbedded Ensures Y2K38 Compliance
32+
===============================================
3333

34-
.. ifconfig:: CONFIG_part_variant in ('AM335X')
34+
Starting with Yocto Nanbield 4.3 (eventually in Scarthgap 5.0), OE-core builds all packages with
35+
the following compile-time defines enabled globally:
3536

36-
https://software-dl.ti.com/cicd-report/linux/index.html?section=platform&platform=am335x
37+
.. code-block:: c
3738
38-
.. ifconfig:: CONFIG_part_variant in ('AM437X')
39+
#define _TIME_BITS 64
40+
#define _FILE_OFFSET_BITS 64
3941
40-
https://software-dl.ti.com/cicd-report/linux/index.html?section=platform&platform=am437x
42+
``_TIME_BITS=64`` instructs glibc to use a 64-bit ``time_t`` on 32-bit platforms, making
43+
all time-related types and functions (``struct timespec``, ``struct timeval``, ``time()``,
44+
``clock_gettime()``, etc.) Y2K38-safe. ``_FILE_OFFSET_BITS=64`` enables large file support
45+
(files >2 GB). Yocto enables both flags together to ensure a consistent 64-bit ABI across
46+
the system.
4147

42-
The above images are based on the 6.6 Kernel and Scarthgap filesystem, and thus has the Y2K38 issue fixed.
48+
Since all packages in the distribution are rebuilt with these defines, the entire filesystem
49+
is consistently Y2K38-safe.
4350

44-
.. note::
45-
While the above images are Y2K38-friendly, it must be ensured that even the code introduced to it from other sources
46-
is Y2K38-friendly. Any code that is not Y2K38-friendly will break the Y2K38-compatibility of the filesystem. Thus it
47-
is important to be intentional about writing Y2K38-friendly code, and to test this code to ensure that the final
48-
image remains Y2K38-friendly.
51+
This approach requires:
4952

50-
To build a Y2K38-friendly image on the 6.6 Kernel and Scarthgap filesystem baseline, follow the "Build Instructions"
51-
section present in the above link.
53+
- **glibc 2.34 or later** — introduces support for ``_TIME_BITS=64`` on 32-bit architectures
54+
- **Linux kernel 5.6 or later** — completes full 64-bit time syscall support
55+
(``clock_gettime64``, ``clock_settime64``, etc.) required by glibc on 32-bit systems
56+
57+
The Scarthgap filesystem satisfies both requirements (ships with glibc 2.39 and kernel 6.6).
58+
59+
Ensuring Your Code is Y2K38-Friendly
60+
====================================
61+
62+
While the SDK images are Y2K38-friendly, any code introduced from external sources must also be
63+
Y2K38-compliant. Code that is not Y2K38-compliant will break the Y2K38-compatibility of the filesystem.
64+
65+
When building applications or libraries to run on the SDK filesystem, ensure the following compile-time
66+
defines are set:
67+
68+
.. code-block:: c
69+
70+
#define _TIME_BITS 64
71+
#define _FILE_OFFSET_BITS 64
72+
73+
Or equivalently, pass these flags to the compiler:
74+
75+
.. code-block:: console
76+
77+
$ CFLAGS="-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64" make
78+
79+
With ``_TIME_BITS=64`` set, standard time functions (``time()``, ``clock_gettime()``,
80+
``localtime()``, etc.) automatically use 64-bit time internally — no API changes are
81+
required. However, audit your code for:
82+
83+
- ``time_t`` casts or assignments that assume a 32-bit (4-byte) size
84+
- Hardcoded Unix timestamps or future dates as raw integer constants
85+
- Use of ``sizeof(time_t)`` in serialization/protocol code
86+
87+
******************************
88+
How to Verify Y2K38 Compliance
89+
******************************
90+
91+
.. warning::
92+
93+
Set the date back to the correct value after testing. Running with an incorrect system clock
94+
can disrupt services such as NTP, certificate validation, and cron jobs.
95+
96+
Check ``sizeof(time_t)``
97+
========================
98+
99+
The quickest way to verify a binary is Y2K38-safe is to check the size of ``time_t`` at
100+
compile time or runtime:
101+
102+
.. code-block:: c
103+
104+
#include <stdio.h>
105+
#include <time.h>
106+
int main(void) {
107+
printf("sizeof(time_t): %zu\n", sizeof(time_t));
108+
return 0;
109+
}
110+
111+
- Compiled **without** ``_TIME_BITS=64``: ``sizeof(time_t)`` = 4 (32-bit, **not Y2K38-safe**)
112+
- Compiled **with** ``_TIME_BITS=64``: ``sizeof(time_t)`` = 8 (64-bit, **Y2K38-safe**)
113+
114+
Test with a Post-2038 Date
115+
==========================
116+
117+
You can also test whether your system handles dates beyond 2038 correctly by temporarily
118+
setting the system clock past January 19, 2038.
119+
120+
**Test procedure:**
121+
122+
#. Save the current date:
123+
124+
.. code-block:: console
125+
126+
$ date
127+
Tue Jan 19 03:00:00 UTC 2038
128+
129+
#. Set the clock past the Y2K38 boundary:
130+
131+
.. code-block:: console
132+
133+
$ date -s "2038-01-20 00:00:00"
134+
135+
#. Verify the system handles the date correctly:
136+
137+
.. code-block:: console
138+
139+
$ date
140+
Wed Jan 20 00:00:00 UTC 2038
141+
$ date +%s
142+
2147558400
143+
144+
On a Y2K38-safe system, ``date +%s`` returns a value greater than ``2147483647``
145+
(0x7FFFFFFF) without overflow or sign error.
146+
147+
#. Restore the correct date:
148+
149+
.. code-block:: console
150+
151+
$ date -s "<correct-date>"
152+
153+
**On a non-Y2K38-safe system**, setting the date past the boundary may cause:
154+
155+
- ``date`` to report a date in 1901 (signed overflow wraps to negative epoch)
156+
- System services to crash or behave unexpectedly
157+
- ``date +%s`` to return a small or negative value

0 commit comments

Comments
 (0)