Bug 12091

Summary: Direct use of __NR_clock_gettime is not time64-safe
Product: Busybox Reporter: bugdal
Component: OtherAssignee: unassigned
Status: RESOLVED FIXED    
Severity: normal CC: busybox-cvs
Priority: P5    
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: Linux   
Host: Target:
Build:

Description bugdal 2019-08-08 06:23:56 UTC
libbb/time.c and coreutils/date.c use syscall(__NR_clock_gettime, ...) rather than calling the clock_gettime function to avoid the need for -lrt on ancient glibc and on uclibc. This will break badly when 32-bit targets change their time_t to 64-bit, when the library "struct timespec" type will no longer match the types used by the legacy time32 clock_gettime syscall.

Both uses should be converted to calls to the clock_gettime function, and makefile logic should be added to link -lrt if needed (perhaps looking for the static version of it so as to pull in just the clock_gettime function, not DT_NEEDED references to a shared library and an indirect reference to libpthread, on glibc and uclibc).

Fixing this will also get vdso clock_gettime support.
Comment 1 bugdal 2019-08-08 06:43:36 UTC
To elaborate, this is going to be hard breakage on one of the next couple musl releases, which will make time_t 64-bit on all archs. Of course distros will patch as needed, but it would be nice to have this fixed upstream.
Comment 2 bugdal 2019-10-24 04:58:30 UTC
Commits 902d399292 and b7b7452f29 attempted to fix this, but the fix is glibc-dependent (uses internal glibc macro __TIMESIZE) and breaks the ability for time64-ready binaries to run on older kernels that lack the time64 syscalls.

I would really like to see this fixed by dropping the whole raw syscall hack and using the public clock_gettime function. This would also enable use of vdso clock_gettime. For ancient glibc (and possibly uclibc?) it needs -lrt, but that could be handled with trylink like -lcrypt, -lm, etc. are now.

If this is unacceptable, I can prepare a patch to fix the above issues. It would condition the time64 code path on sizeof(time_t) rather than __TIMESIZE and would in that case use __NR_clock_gettime64 if it's defined, falling back if it's not defined or if it fails with ENOSYS (older kernels) to __NR_clock_gettime and converting the results if sizeof(long)<sizeof(time_t).

As the code stands now, it is going to break on all 32-bit archs with the next release of musl.
Comment 3 Denys Vlasenko 2019-10-24 14:50:38 UTC
Fixed in git:

commit be5a505d771a77c640acc35ceaa470c80e62f954
Author: Denys Vlasenko <vda.linux@googlemail.com>
Date:   Thu Oct 24 16:26:55 2019 +0200

    Remove syscall wrappers around clock_gettime