7. “time_t” stores system time
Since: midnight UTC of January 1, 1970
7
The time_t datatype is a data type in the ISO C library and kernel structure
defined for storing system time values.
32-bit system can represent dates from [2]
Dec 13 1901
Jan 19th 2038
It causes integer overflowing on 03:14:08 UTC 19 January 2038
11. Why 32-bit system [1]
11
1
Long-term Support
there are 32-bit systems being deployed now that can be
expected to have lifetimes of 24 years or longer.
2
64-bit is Overkill
32-bit systems are likely to continue to be made for far longer
than most people might expect. (e.g., micro-controller)
12. OpenBSD solution
Be suitable for self-contained system
12
Changes types like
time_t and clock_t
to 64-bit quantities [3]
DANGER:
ABI incompatibility. Updating to this kernel requires extra
work or you won't be able to login: install a snapshot instead.
[3]
19. converting system calls to 64-bit time_t [15]
19
All system calls are changed to 64-bit type and added CONFIG_COMPAT_TIME
for compatibility, but it is not accepted by kernel so far [15]
21. Current Syscall with y2038 (1/4)
syscalls that are impacted by 64-bit time_t [14]
21
class syscall name argument direction replacement range needed
64-bit
argument alternatives
incompatible
args
clocks
time time_t out clock_gettime
stime time_t in clock_settime
gettimeofday timeval out clock_gettime
settimeofday timeval in clock_settime
adjtimex timex inout clock_adjtime
nanosleep timespec inout clock_nanosleep
clock_gettime timespec out 64 timespec64 ktime_t? -
clock_settime timespec inout 64 timespec64 ktime_t? -
clock_adjtime timex inout 64 timex64 ktime_t? -
clock_getres timespec out 32 timespec64 ktime_t? -
clock_nanosleep timespec inout 64 timespec64 ktime_t? -
alarm int in timer_settime
22. Current Syscall with y2038 (2/4)
syscalls that are impacted by 64-bit time_t [14]
22
class syscall name argument direction replacement
range
needed
64-bit
argument alternatives
incompatible
args
timers
getitimer itimerval out timer_gettime
setitimer itimerval inout timer_settime
timer_gettime itimerspec out 64 itimespec64 ktime_t? -
timer_settime itimerspec inout 64 itimespec64 ktime_t? -
timerfd_gettime itimerspec out 64 itimespec64 ktime_t? -
timerfd_settime itimerspec inout 64 itimespec64 ktime_t? -
I/O
select timeval inout pselect6
old_select sel_arg_structinout pselect6
pselect6 timespec inout 32 timespec64 ktime_t? fd_set, sigset
ppoll timespec inout 32 timespec64 ktime_t? sigset
io_getevents timespec in 32 timespec64 ktime_t? -
recvmmsg timespec inout 32 timespec64 ktime_t? mmsghdr
23. Current Syscall with y2038 (3/4)
syscalls that are impacted by 64-bit time_t [14]
23
class syscall name argument direction replacement
range
needed
64-bit
argument alternatives
incompatible
args
ipc
mq_timedsend timespec in 64 timespec64 ktime_t? -
mq_timedreceive timespec in 64 timespec64 ktime_t? -
semtimedop timespec in 32 timespec64 jiffies? -
msgctl msqid_ds out 64 msqid_ds64 - -
semctl semid_ds out 64 semid_ds64 - -
shmctl shmid_ds out 64 shmid_ds64 - -
tasks
rt_sigtimedwait timespec inout 32 timespec64 jiffies? sigset, siginfo
futex timespec in 64 timespec64 ktime_t? -
sched_rr_get_interval timespec out 32 timespec64 leave 32-bit -
getrusage
rusage
(timeval) out 32 rusage64 leave 32-bit -
wait4
rusage
(timeval) out waitid
waitid
rusage
(timeval) out 32 rusage64 leave 32-bit siginfo
system sysinfo sysinfo out 32 leave 32-bit - -
24. Current Syscall with y2038 (4/4)
syscalls that are impacted by 64-bit time_t [14]
24
class syscall name argument direction replacement
range
needed
64-bit
argument alternatives
incompatible
args
inodes
utime utimbuf in utimensat
utimes timeval in utimensat
futimensat timeval in utimensat
utimensat timespec in 64 timespec64 timespec64 -
oldstat
__old_kernel_s
tat out stat64
oldlstat
__old_kernel_s
tat out lstat64
oldfstat
__old_kernel_s
tat out fstat64
newstat stat out stat64
newlstat stat out lstat64
newfstat stat out fstat64
newfstatat stat out fstatat64
stat64 stat64 out fstatat64
lstat64 stat64 out fstatat64
fstat64 stat64 out 64 stat6464 new struct -
fstatat64 stat64 out 64 stat6464 new struct -
26. Fixing filesystem timestamps
EXT4 takes “extra” bit to extend timestamp size to 34-bit
26
Within this "extra" 32-bit field,
the lower two bits are used to
extend the 32-bit seconds field to
be 34 bit wide; the upper 30 bits
are used to provide nanosecond
timestamp accuracy. Therefore,
timestamps should not overflow
until May 2446. [8]
27. Fixing EXT4 timestamps
EXT4 is still not y2038 safe now [10]
27
Patch is ready but not accepted by kernel yet
EXT4 has some y2038 unsafe variables
28. Current filesystem with y2038 (1/3)
Overview of file systems [9]
28
file system time type expiration year
9p (9P2000) unsigned 32-bit seconds 2106
file system time type expiration year
9p (9P2000) unsigned 32-bit seconds 2106
9p (9P2000.L) signed 64-bit seconds, ns never
adfs 40-bit cs since 1900 2248
affs u32 days/mins/(secs/50) 11760870
afs unsigned 32-bit seconds 2106
befs unsigned 48-bit seconds never
bfs unsigned 32-bit seconds 2106
btrfs signed 64-bit seconds, 32-bit ns never
ceph unsigned 32-bit second/ns 2106
cifs (smb) 7-bit years since 1980 2107
cifs (modern) 64-bit 100ns since 1601 30328
coda timespec ioctl 2038
cramfs fixed 1970
efs unsigned 32-bit seconds 2106
exofs signed 32-bit seconds 2038
ext2 signed 32-bit seconds 2038
ext3 signed 32-bit seconds 2038
ext4 (good old inodes) signed 32-bit seconds 2038
ext4 (new inodes 34 bit seconds / 30-bit ns (but broken) 2038
f2fs 64-bit seconds / 32-bit ns never
29. Current filesystem with y2038 (2/3)
Overview of file systems [9]
29
file system time type expiration year
fat 7-bit years since 1980, 2s resolution 2107
freevxfs unsigned 32-bit seconds/u32 microseconds 2106
fuse 64-bit second/32-bit ns never
gfs2 u64 seconds/u32 ns never
hfs u32 seconds since 1904 2040
hfsplus u32 seconds since 1904 2040
hostfs timespec 2038
hpfs unsigned 32-bit seconds 2106
isofs 'char' year since 1900 (fixable) 2028
jffs2 unsigned 32-bit seconds 2106
jfs unsigned 32-bit seconds/ns 2106
logfs signed 64-bit ns 2262
minix unsigned 32-bit seconds 2106
ncpfs 7-bit year since 1980 2107
nfsv2,v3 unsigned 32-bit seconds/ns 2106
nfsv4 u64 seconds/u32 ns never
nfsd unsigned 32-bit seconds/ns 2106
nilfs2 u64 seconds/u32 ns never
ntfs 64-bit 100ns since 1601 30828
ocfs2 34-bit seconds/30-bit ns 2514
omfs 64-bit milliseconds never
pstore ascii seconds 2106
30. Current filesystem with y2038 (3/3)
Overview of file systems [9]
30
file system time type expiration year
qnx4 unsigned 32-bit seconds 2106
qnx6 unsigned 32-bit seconds 2106
reiserfs unsigned 32-bit seconds 2106
romfs fixed 1970
squashfs unsigned 32-bit seconds 2106
sysv unsigned 32-bit seconds 2106
ubifs u64 second/u32 ns never
udf u16 year 2038
ufs1 unsigned 32-bit seconds 2106
ufs2 signed 64-bit seconds/u32 ns never
xfs signed 32-bit seconds/ns 2106
32. Plan for VFS with y2038 [9]
32
Milestone # of patches Status
Targeted Kernel
release
Infrastructure patches for vfs_time and granularity fields 1.4.1 and 1.4.2 2 Done 4.7- rc1
Test time ranges beyond y2038 support, in memory timestamps match
with on disk -1.3.1 and 1.3.2
Xfs tests In progress 5/28/16
Replace CURRENT_TIME and CURRENT_TIME_SEC – 1.2.1 ~60
In Progress, waiting for 4.7 rc1
and repost previous.
4.8
Vfs_time patches – 1.4.3 ~40 In Progress, waiting for 4.7-rc1 4.8
Fill in right granularities and ranges for FS – 1.2.2 and 1.2.3 ~40 Yet to start 4.8
Expose FS granularities and ranges – 1.4.5 and 1.4.6 ~5 Yet to start 4.8
Tests to check the granularities and ranges – 1.3.3 and 1.3.4 Xfs tests Yet to start 6/10/16
Add policy for wrong granularities - 1.4.7 RFC for 4.9 Yet to start
Stat and utime changes – 1.4.8 RFC for 4.9 Yet to start
Tests for I_DIRTY_* flags and mount options -1.3.5 and 1.3.6 Xfs tests Yet to start 6/30/16
Transition vfs to 64 bit – 1.4.4 2
Ready, wait for other patches to
merge
4.10
33. Use monotonic clock instead
of wall time
33
y2038 unsafe.
an integer overflow might be occurred
36. User space
36
Kernel and GLIBC might be
incompatible
1
32-bit/ 64-bit use the same name of APIs
User need to define application code “_TIME_BITS=64” to get 64-bit
time support
32-bit time APIs are default setting on 32-bit systems
On 32-bit systems, if __USE_TIME_BITS64 is defined, time support is
provided for 64-bit time; otherwise, it is provided for 32-bit time.[5]
2
37. Definite & Debatable [5]
37
Definite
1. 64-bit time would be supported as a replacement of 32-bit time; user code (including libraries) would require
either 32-bit or 64-bit time support, with 32-bit remaining the default for now.
2. Any newly introduced function MUST be declared in the implementation, not user, namespace (see
https://sourceware.org/bugzilla/show_bug.cgi?id=14106).
3. Any newly introduced struct MUST have a name (see https://sourceware.org/bugzilla/show_bug.cgi?id=15766).
Debatable (Should be removed)
1. 64-bit time should only be supported if 64-bit file offsets are. This sounds like something totally unrelated, but
the underlying idea is to not multiply the possible combinations.
2. 32-bit time support will not be modified; 32-bit time functions which returns wrong results now will keep
returning wrong results after introduction of 64-bit time support. IOW, this design does not aim at trying to fix
existing 32-bit time support at all; any fix to the Y2038 problem will be within new 64-bit time support.
3. Make sure no change affects 64-bit platforms where time_t is already 64-bit (see
http://www.sourceware.org/ml/libc-alpha/2015-08/msg00038.html).
38. Time-related GLIBC APIs (1/3) [5]
38
Function Y2038-unsafe?
time_t YES, as time_t is 32-bit signed on 32-bit builds
double difftime (time_t time1, time_t time0) YES, as time_t is Y2038-unsafe
struct timeval { time_t tv_sec; long int tv_usec; } YES, as time_t is Y2038-unsafe
struct timespec { time_t tv_sec; long int tv_nsec; } YES, as time_t is Y2038-unsafe
clock_t clock(void)
No, return value is not clock time in seconds since the epoch but CPU time
in clock ticks
struct tms { clock_t tms_utime; clock_t tms_stime; clock_t tms_cutime; clo
ck_t tms_cstime; }
No, as all members are Y2038-safe
clock_t times(struct tms *buffer) No, as struct tms is Y2038-safe
time_t time (time_t *result) YES, as time_t is Y2038-unsafe
int stime (const time_t *newtime) YES, as time_t is Y2038-unsafe
struct timezone { int tz_minuteswest; int tz_dsttime; } No
struct timeval YES, as struct timeval depends on time_t which is Y2038-unsafe
int gettimeofday (struct timeval *tp, struct timezone *tzp) YES, as struct timeval is Y2038-unsafe
int settimeofday (const struct timeval *tp, const struct timezone *tzp) YES, as struct timeval is Y2038-unsafe
int adjtime (const struct timeval *delta, struct timeval *olddelta) YES, as struct timeval is Y2038-unsafe
struct timex YES, as struct timex depends on struct timeval which is Y0238-unsafe
int adjtimex (struct timex *timex) YES, as struct timex is Y0238-unsafe
struct tm { int tm_sec; int tm_min; ... } No, as all members are Y2038-safe
39. Time-related GLIBC APIs (2/3) [5]
39
Function Y2038-unsafe?
struct tm * localtime (const time_t *time) YES, as time_t is Y2038-unsafe
struct tm * localtime_r (const time_t *time, struct tm *resultp) YES, as time_t is Y2038-unsafe
struct tm * gmtime (const time_t *time) YES, as time_t is Y2038-unsafe
struct tm * gmtime_r (const time_t *time, struct tm *resultp) YES, as time_t is Y2038-unsafe
time_t mktime (struct tm *brokentime) YES, as time_t is Y2038-unsafe
time_t timelocal (struct tm *brokentime) YES, as time_t is Y2038-unsafe
time_t timegm (struct tm *brokentime) YES, as time_t is Y2038-unsafe
struct ntptimeval { struct timeval time; long int maxerror; long int esterr
or; }
YES, as struct timeval is Y2038-unsafe
struct ntptimeval
YES, as struct ntptimeval depends on struct timeval which is Y2038-
unsafe
ntp_gettime (struct ntptimeval *tptr) YES, as struct ntptimeval is Y2038-unsafe
struct timex { ... struct timeval time; ... } YES, as struct timeval time is Y2038-unsafe
int ntp_adjtime (struct timex *tptr) YES, as struct timex is Y2038-unsafe
char * asctime (const struct tm *brokentime) No, as struct tm is Y2038-safe
char * asctime_r (const struct tm *brokentime, char *buffer) No, as struct tm is Y2038-safe
char * ctime (const time_t *time) YES, as time_t is Y2038-unsafe
char * ctime_r (const time_t *time, char *buffer) YES, as time_t is Y2038-unsafe
size_t strftime (char *s, size_t size, const char *template, const struct tm *
brokentime)
No, as struct tm is Y2038-safe
size_t wcsftime (wchar_t *s, size_t size, const wchar_t *template, const str
uct tm *brokentime)
No, as struct tm is Y2038-safe
40. Time-related GLIBC APIs (3/3) [5]
40
Function Y2038-unsafe?
char * strptime (const char *s, const char *fmt, struct tm *tp
)
No, as struct tm is Y2038-safe
struct tm * getdate (const char *string) No, as struct tm is Y2038-safe
int getdate_r (const char *string, struct tm *tp) No, as struct tm is Y2038-safe
struct itimerval
YES, as struct timeval depends on struct timeval which is
Y2038-unsafe
int setitimer (int which, const struct itimerval *new, struct i
timerval *old)
YES, as struct itimerval is Y2038-unsafe
int getitimer (int which, struct itimerval *old) YES as struct itimerval is Y2038-unsafe
unsigned int alarm (unsigned int seconds) TBC depending on implementation
unsigned int sleep (unsigned int seconds) TBC depending on implementation
int nanosleep (const struct timespec *requested_time, stru
ct timespec *remaining)
YES, as struct timespec is Y2038-unsafe
41. Other GLIBC APIs (1/2) [5]
41
Function Y2038-unsafe?
Section 22.1 - Resource Usage
struct rusage { struct timeval ru_utime; struct timeval ru_st
ime; ... }
YES, as struct_timeval is Y2038-unsafe
int getrusage (int processes, struct rusage *rusage) YES, as struct_rusage is Y2038-unsafe
struct vtimes { struct timeval vm_utime; struct timeval vm_
stime; ... }
YES, as struct_timeval is Y2038-unsafe
int vtimes (struct vtimes *current, struct vtimes *child) YES, as struct_vtimes is Y2038-unsafe
Section 22.2 - Resource Limitation
rlim_t
No, as the value held is an amount of seconds, not an
absolute date
int sched_rr_get_interval (pid_t pid, struct timespec *interva
l)
No, as the value returned is a small interval, typically 150 µs)
42. Other GLIBC APIs (2/2) [5]
42
Function Y2038-unsafe?
Section 22.1 - Resource Usage
struct rusage { struct timeval ru_utime; struct timeval ru_stime;
... }
YES, as struct_timeval is Y2038-unsafe
int getrusage (int processes, struct rusage *rusage) YES, as struct_rusage is Y2038-unsafe
struct vtimes { struct timeval vm_utime; struct timeval vm_stim
e; ... }
YES, as struct_timeval is Y2038-unsafe
int vtimes (struct vtimes *current, struct vtimes *child) YES, as struct_vtimes is Y2038-unsafe
Section 22.2 - Resource Limitation
rlim_t
No, as the value held is an amount of seconds, not an absolute
date
int sched_rr_get_interval (pid_t pid, struct timespec *interval) No, as the value returned is a small interval, typically 150 µs)
43. 43
Conclusion
Be aware when coding AP/ driver with 32-bit
machine
Don’t use y2038-unsafe value/ structure in driver
Don’t use y2038-unsafe value/ structure in application
1
2
3
The solution is not confirmed yet
Keep a close eye on tracking
Kernel patch
GLIBC patch
Upgrade existence AP/ driver
The assignment of Job Factors should be completed by the junior
R&D – this bug will hurt their supplemental retirement planning
45. 45
References
1. 2038 is closer than it seems
https://lwn.net/Articles/599580/
2. The end of time
http://elinux.org/images/6/6e/End_of_Time_--
_Embedded_Linux_Conference_2015.pdf
3. CVS: cvs.openbsd.org: src
http://marc.info/?l=openbsd-cvs&m=137637321205010&w=2
4. Pondering 2038
https://lwn.net/Articles/563285/
5. Third draft of the glibc Y2038 design document
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign?rev=63
6. y2038
http://kernelnewbies.org/y2038
7. Heading toward 2038-safe filesystems
https://lwn.net/Articles/672576/
8. Ext4 Disk Layout
https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps
9. y2038/vfs
http://kernelnewbies.org/y2038/vfs
10. fs: ext4: Use current_fs_time() for inode timestamps
https://patchwork.kernel.org/patch/9166291/
11. System call conversion for year 2038
https://lwn.net/Articles/643234/
12. isdn: Use ktime_t instead of 'struct timeval
https://patchwork.kernel.org/patch/7516841/
13. net: ipv4: tcp_probe: Replace timespec with timespec64
https://patchwork.ozlabs.org/patch/589342/
14. posix timers:Introduce the 64bit methods with ti
http://thread.gmane.org/gmane.linux.kernel.cross-arch/27249
15. converting system calls to 64-bit time_t
https://lists.linaro.org/pipermail/y2038/2015-May/000233.html
OpenBSD can do this because it is a self-contained system, with the kernel and user space built together out of a single repository.
openBSD kernel 跟 user space 是在一起的
但 Linux 是分開且要 ABI 兼容
舊的東西 – 修正且 compatible
新的東西 – 要修正
修正目前的東西, 並兼容
1. 使用相對時間而不是絕對時間
code that is used for CONFIG_COMPAT_TIME is shared between 32-bit and 64-bit architectures that provide support for existing 32-bit binaries with 32-bit time_t
b) code that is defined under CONFIG_COMPAT is only used on 64-bit machines to provide support for 32-bit binaries, either system calls that do not use time_t or (rare) that use a 64-bit time_t in compat mode.
fs/ext4/ext4.h
fs/ext4/ext4.h
fs/ext4/ext4.h
fs/ext4/ext4.h
fs/ext4/ext4.h
The VFS layer, on the other hand, has its own timestamp handling for its in-memory inodes and other structures. It will need to change too, but there are various carts and horses that need to be aligned correctly before that can happen. [7]