diff mbox series

[v3] Define in_int32_t_range to check if the 64 bit time_t syscall should be used

Message ID 20221108044945.2173509-1-yunqiang.su@cipunited.com
State New
Headers show
Series [v3] Define in_int32_t_range to check if the 64 bit time_t syscall should be used | expand

Commit Message

YunQiang Su Nov. 8, 2022, 4:49 a.m. UTC
Currently glibc uses in_time_t_range to detects time_t overflow,
and if it occurs fallbacks to 64 bit syscall version.

The function name is confusing because internally time_t might be
either 32 bits or 64 bits (depending on __TIMESIZE).

This patch refactors the in_time_t_range by replacing it with
in_int32_t_range for the case to check if the 64 bit time_t syscall
should be used.

The in_time_t range is used to detect overflow of the
syscall return value.
---
 include/time.h                            | 10 +++++++++-
 nptl/futex-internal.c                     |  4 ++--
 sysdeps/unix/sysv/linux/clock_adjtime.c   |  2 +-
 sysdeps/unix/sysv/linux/clock_nanosleep.c |  2 +-
 sysdeps/unix/sysv/linux/clock_settime.c   |  2 +-
 sysdeps/unix/sysv/linux/mq_timedreceive.c |  2 +-
 sysdeps/unix/sysv/linux/mq_timedsend.c    |  2 +-
 sysdeps/unix/sysv/linux/ppoll.c           |  2 +-
 sysdeps/unix/sysv/linux/pselect.c         |  2 +-
 sysdeps/unix/sysv/linux/recvmmsg.c        |  2 +-
 sysdeps/unix/sysv/linux/select.c          |  2 +-
 sysdeps/unix/sysv/linux/semtimedop.c      |  2 +-
 sysdeps/unix/sysv/linux/setitimer.c       |  4 ++--
 sysdeps/unix/sysv/linux/setsockopt.c      |  2 +-
 sysdeps/unix/sysv/linux/sigtimedwait.c    |  2 +-
 sysdeps/unix/sysv/linux/timer_settime.c   |  4 ++--
 sysdeps/unix/sysv/linux/timerfd_settime.c |  4 ++--
 sysdeps/unix/sysv/linux/utimensat.c       |  4 ++--
 18 files changed, 31 insertions(+), 23 deletions(-)

Comments

Arnd Bergmann Nov. 8, 2022, 10:39 a.m. UTC | #1
On Tue, Nov 8, 2022, at 05:49, YunQiang Su wrote:
> Currently glibc uses in_time_t_range to detects time_t overflow,
> and if it occurs fallbacks to 64 bit syscall version.
>
> The function name is confusing because internally time_t might be
> either 32 bits or 64 bits (depending on __TIMESIZE).
>
> This patch refactors the in_time_t_range by replacing it with
> in_int32_t_range for the case to check if the 64 bit time_t syscall
> should be used.
>
> The in_time_t range is used to detect overflow of the
> syscall return value.

It looks like the fallback logic has another flaw, I don't
see how this works on kernels with COMPAT_32BIT_TIME disabled,
as these only have the time64 syscalls available.

I think for the syscall wrappers implementing the time64
interfaces, there should not be any in_time_t_range()
check, but instead they can just call the time64 syscall
first and only fall back to the time32 version if that
fails with ENOSYS on pre-5.1 kernels. As a side-effect that
would also make it slightly faster on modern kernels
(skipping the pointless range check), at the cost of
being a bit slower on old kernels that require the fallback.

    Arnd
Florian Weimer Nov. 8, 2022, 11:17 a.m. UTC | #2
* Arnd Bergmann:

> On Tue, Nov 8, 2022, at 05:49, YunQiang Su wrote:
>> Currently glibc uses in_time_t_range to detects time_t overflow,
>> and if it occurs fallbacks to 64 bit syscall version.
>>
>> The function name is confusing because internally time_t might be
>> either 32 bits or 64 bits (depending on __TIMESIZE).
>>
>> This patch refactors the in_time_t_range by replacing it with
>> in_int32_t_range for the case to check if the 64 bit time_t syscall
>> should be used.
>>
>> The in_time_t range is used to detect overflow of the
>> syscall return value.
>
> It looks like the fallback logic has another flaw, I don't
> see how this works on kernels with COMPAT_32BIT_TIME disabled,
> as these only have the time64 syscalls available.

Isn't that an invalid kernel configuration?

Thanks,
Florian
Arnd Bergmann Nov. 8, 2022, 11:33 a.m. UTC | #3
On Tue, Nov 8, 2022, at 12:17, Florian Weimer wrote:
> * Arnd Bergmann:
>> On Tue, Nov 8, 2022, at 05:49, YunQiang Su wrote:
>>> Currently glibc uses in_time_t_range to detects time_t overflow,
>>> and if it occurs fallbacks to 64 bit syscall version.
>>>
>>> The function name is confusing because internally time_t might be
>>> either 32 bits or 64 bits (depending on __TIMESIZE).
>>>
>>> This patch refactors the in_time_t_range by replacing it with
>>> in_int32_t_range for the case to check if the 64 bit time_t syscall
>>> should be used.
>>>
>>> The in_time_t range is used to detect overflow of the
>>> syscall return value.
>>
>> It looks like the fallback logic has another flaw, I don't
>> see how this works on kernels with COMPAT_32BIT_TIME disabled,
>> as these only have the time64 syscalls available.
>
> Isn't that an invalid kernel configuration?

No, this is what we will use anyway after 2038 (possibly
earlier), so the option is useful to ensure that all userspace
has been converted away from the time32 interfaces.

     Arnd
Florian Weimer Nov. 8, 2022, 11:39 a.m. UTC | #4
* Arnd Bergmann:

> On Tue, Nov 8, 2022, at 12:17, Florian Weimer wrote:
>> * Arnd Bergmann:
>>> On Tue, Nov 8, 2022, at 05:49, YunQiang Su wrote:
>>>> Currently glibc uses in_time_t_range to detects time_t overflow,
>>>> and if it occurs fallbacks to 64 bit syscall version.
>>>>
>>>> The function name is confusing because internally time_t might be
>>>> either 32 bits or 64 bits (depending on __TIMESIZE).
>>>>
>>>> This patch refactors the in_time_t_range by replacing it with
>>>> in_int32_t_range for the case to check if the 64 bit time_t syscall
>>>> should be used.
>>>>
>>>> The in_time_t range is used to detect overflow of the
>>>> syscall return value.
>>>
>>> It looks like the fallback logic has another flaw, I don't
>>> see how this works on kernels with COMPAT_32BIT_TIME disabled,
>>> as these only have the time64 syscalls available.
>>
>> Isn't that an invalid kernel configuration?
>
> No, this is what we will use anyway after 2038 (possibly
> earlier), so the option is useful to ensure that all userspace
> has been converted away from the time32 interfaces.

What happened to not breaking userspace?

Those with 32-bit applications will want to run their legacy stuff in a
time-shifted environment, so these system calls must remain supported
outside specialized applications.

Thanks,
Florian
Adhemerval Zanella Netto Nov. 8, 2022, 11:55 a.m. UTC | #5
On 08/11/22 08:39, Florian Weimer wrote:
> * Arnd Bergmann:
> 
>> On Tue, Nov 8, 2022, at 12:17, Florian Weimer wrote:
>>> * Arnd Bergmann:
>>>> On Tue, Nov 8, 2022, at 05:49, YunQiang Su wrote:
>>>>> Currently glibc uses in_time_t_range to detects time_t overflow,
>>>>> and if it occurs fallbacks to 64 bit syscall version.
>>>>>
>>>>> The function name is confusing because internally time_t might be
>>>>> either 32 bits or 64 bits (depending on __TIMESIZE).
>>>>>
>>>>> This patch refactors the in_time_t_range by replacing it with
>>>>> in_int32_t_range for the case to check if the 64 bit time_t syscall
>>>>> should be used.
>>>>>
>>>>> The in_time_t range is used to detect overflow of the
>>>>> syscall return value.
>>>>
>>>> It looks like the fallback logic has another flaw, I don't
>>>> see how this works on kernels with COMPAT_32BIT_TIME disabled,
>>>> as these only have the time64 syscalls available.
>>>
>>> Isn't that an invalid kernel configuration?
>>
>> No, this is what we will use anyway after 2038 (possibly
>> earlier), so the option is useful to ensure that all userspace
>> has been converted away from the time32 interfaces.
> 
> What happened to not breaking userspace?
> 
> Those with 32-bit applications will want to run their legacy stuff in a
> time-shifted environment, so these system calls must remain supported
> outside specialized applications.
> 
> Thanks,
> Florian

I agree and the time64 support was added based on this assumption.  I
understand that this simplifies the code and kernel attack surface,
but it a userspace breakage anyhow.
Arnd Bergmann Nov. 8, 2022, 12:28 p.m. UTC | #6
On Tue, Nov 8, 2022, at 12:39, Florian Weimer wrote:
>> On Tue, Nov 8, 2022, at 12:17, Florian Weimer wrote:
>>> * Arnd Bergmann:
>>>> On Tue, Nov 8, 2022, at 05:49, YunQiang Su wrote:
>>>
>>> Isn't that an invalid kernel configuration?
>>
>> No, this is what we will use anyway after 2038 (possibly
>> earlier), so the option is useful to ensure that all userspace
>> has been converted away from the time32 interfaces.
>
> What happened to not breaking userspace?

It's a configuration option that makes sense for some users
but not others, just like a lot of other conditional system
calls that we have (UID16, IPC, SGETMASK_SYSCALL, FUTEX, EVENTPOLL,
INOTIFY, IO_URING, AIO, TIMERFD, QUOTA, MODULES).

If you turn these compile-time symbols off, you naturally break
compatibility with any applications and libraries that call the
corresponding syscalls, but nevertheless there are embedded
systems that never need to call them and prefer to leave the
symbols disabled.

If you know you run a modern glibc, you probably don't
care about uid16 syscalls or sgetmask/ssetmask and can
leave them disabled. Similarly, system calls that have
not been used for a long time eventually get removed
completely, with extreme caution. Examples include prof(),
lock(), afs_syscall(), pkey_set(), or ftime(). uselib() may
be next on the list.

For embedded systems, being able to turn off the broken
time32 interfaces right now is fairly important, otherwise
it is excessively hard to validate that a system is not
accidentally calling the wrong interfaces or relying on
fallbacks that no longer work after 2038.

For a desktop distro, that obviously does not apply, as
users need to be able to run arbitrary binaries that
were built for time32 or uid16.

> Those with 32-bit applications will want to run their legacy stuff in a
> time-shifted environment, so these system calls must remain supported
> outside specialized applications.

We have had several discussions about adding time-shifting
for CLOCK_REALTIME to the kernel, and always concluded that
the added complexity is not worth the possible benefit
(unlike shifting CLOCK_MONOTONIC, which has use cases for
checkpoint/restart).

Clearly one can do the same thing using some LD_PRELOAD
library or a virtual machine, but then again if you do this,
you can also have that LD_PRELOAD library do the conversion
to the time64 interfaces, or have the VM run a kernel with
the time32 syscalls still present.

     Arnd
Adhemerval Zanella Netto Nov. 8, 2022, 12:51 p.m. UTC | #7
On 08/11/22 09:28, Arnd Bergmann wrote:
> On Tue, Nov 8, 2022, at 12:39, Florian Weimer wrote:
>>> On Tue, Nov 8, 2022, at 12:17, Florian Weimer wrote:
>>>> * Arnd Bergmann:
>>>>> On Tue, Nov 8, 2022, at 05:49, YunQiang Su wrote:
>>>>
>>>> Isn't that an invalid kernel configuration?
>>>
>>> No, this is what we will use anyway after 2038 (possibly
>>> earlier), so the option is useful to ensure that all userspace
>>> has been converted away from the time32 interfaces.
>>
>> What happened to not breaking userspace?
> 
> It's a configuration option that makes sense for some users
> but not others, just like a lot of other conditional system
> calls that we have (UID16, IPC, SGETMASK_SYSCALL, FUTEX, EVENTPOLL,
> INOTIFY, IO_URING, AIO, TIMERFD, QUOTA, MODULES).
> 
> If you turn these compile-time symbols off, you naturally break
> compatibility with any applications and libraries that call the
> corresponding syscalls, but nevertheless there are embedded
> systems that never need to call them and prefer to leave the
> symbols disabled.
> 
> If you know you run a modern glibc, you probably don't
> care about uid16 syscalls or sgetmask/ssetmask and can
> leave them disabled. Similarly, system calls that have
> not been used for a long time eventually get removed
> completely, with extreme caution. Examples include prof(),
> lock(), afs_syscall(), pkey_set(), or ftime(). uselib() may
> be next on the list.
> 
> For embedded systems, being able to turn off the broken
> time32 interfaces right now is fairly important, otherwise
> it is excessively hard to validate that a system is not
> accidentally calling the wrong interfaces or relying on
> fallbacks that no longer work after 2038.
> 
> For a desktop distro, that obviously does not apply, as
> users need to be able to run arbitrary binaries that
> were built for time32 or uid16.

Sigh, I have added the use of 64 bit syscall if required for some
sysmbols because I assumed that 32 bit time_t syscall would be always
available.  This is small optimization to avoid issuing a lot of
64 bit syscall, specially for syscall like futex.

But if kernel does indeed assume that COMPAT_32BIT_TIME is a supported
configuration I think we will need to roll out the optimization and
always issue the 64 bit time_t syscalls anyway.  From a glibc point of
view it should not matter much besides some small overhead for newer
glibc running on older kernels (we might add a global to disable the
64-bit call if kernel does not support, as we do for some specific
syscalls).

> 
>> Those with 32-bit applications will want to run their legacy stuff in a
>> time-shifted environment, so these system calls must remain supported
>> outside specialized applications.
> 
> We have had several discussions about adding time-shifting
> for CLOCK_REALTIME to the kernel, and always concluded that
> the added complexity is not worth the possible benefit
> (unlike shifting CLOCK_MONOTONIC, which has use cases for
> checkpoint/restart).
> 
> Clearly one can do the same thing using some LD_PRELOAD
> library or a virtual machine, but then again if you do this,
> you can also have that LD_PRELOAD library do the conversion
> to the time64 interfaces, or have the VM run a kernel with
> the time32 syscalls still present.
> 
>      Arnd
Arnd Bergmann Nov. 8, 2022, 1:27 p.m. UTC | #8
On Tue, Nov 8, 2022, at 13:51, Adhemerval Zanella Netto wrote:
> On 08/11/22 09:28, Arnd Bergmann wrote:
>
> Sigh, I have added the use of 64 bit syscall if required for some
> sysmbols because I assumed that 32 bit time_t syscall would be always
> available.  This is small optimization to avoid issuing a lot of
> 64 bit syscall, specially for syscall like futex.
>
> But if kernel does indeed assume that COMPAT_32BIT_TIME is a supported
> configuration I think we will need to roll out the optimization and
> always issue the 64 bit time_t syscalls anyway.  From a glibc point of
> view it should not matter much besides some small overhead for newer
> glibc running on older kernels (we might add a global to disable the
> 64-bit call if kernel does not support, as we do for some specific
> syscalls).

It's possible that I have misread what glibc does at the moment,
as I see there are checks for __ASSUME_TIME64_SYSCALLS in the
same code path.

To clarify: I think an important configuration is one where
an embedded system assumes both kernel and userspace are
always modern and only support time64. This means
CONFIG_COMPAT_32BIT_TIME is disabled in the kernel, and glibc
is built to only support a modern enough kernel to assume
time64 support is always available. I have not tested whether
this works at the moment, but it probably does not require
a large rework if there is something still missing. Sorry
for having hijacked this thread if this is already supported.

If glibc is configured to support older linux-3.2 and includes
the time32 fallbacks for that, it's not unreasonable to require
CONFIG_COMPAT_32BIT_TIME=y for those. It would be
good to document this dependency, or even have an early
runtime check similar to the "kernel too old" error that
glibc produces when there is a version mismatch.

      Arnd
Adhemerval Zanella Netto Nov. 8, 2022, 1:49 p.m. UTC | #9
On 08/11/22 10:27, Arnd Bergmann wrote:
> On Tue, Nov 8, 2022, at 13:51, Adhemerval Zanella Netto wrote:
>> On 08/11/22 09:28, Arnd Bergmann wrote:
>>
>> Sigh, I have added the use of 64 bit syscall if required for some
>> sysmbols because I assumed that 32 bit time_t syscall would be always
>> available.  This is small optimization to avoid issuing a lot of
>> 64 bit syscall, specially for syscall like futex.
>>
>> But if kernel does indeed assume that COMPAT_32BIT_TIME is a supported
>> configuration I think we will need to roll out the optimization and
>> always issue the 64 bit time_t syscalls anyway.  From a glibc point of
>> view it should not matter much besides some small overhead for newer
>> glibc running on older kernels (we might add a global to disable the
>> 64-bit call if kernel does not support, as we do for some specific
>> syscalls).
> 
> It's possible that I have misread what glibc does at the moment,
> as I see there are checks for __ASSUME_TIME64_SYSCALLS in the
> same code path.
> 
> To clarify: I think an important configuration is one where
> an embedded system assumes both kernel and userspace are
> always modern and only support time64. This means
> CONFIG_COMPAT_32BIT_TIME is disabled in the kernel, and glibc
> is built to only support a modern enough kernel to assume
> time64 support is always available. I have not tested whether
> this works at the moment, but it probably does not require
> a large rework if there is something still missing. Sorry
> for having hijacked this thread if this is already supported.
> 
> If glibc is configured to support older linux-3.2 and includes
> the time32 fallbacks for that, it's not unreasonable to require
> CONFIG_COMPAT_32BIT_TIME=y for those. It would be
> good to document this dependency, or even have an early
> runtime check similar to the "kernel too old" error that
> glibc produces when there is a version mismatch.

Yes, the 32 bit fallback assumes that you either use the default minimum
kernel or configure with --enable-kernel with a value lower than 5.1.
And the optimization such as ecf2661281c was added on the basis that for
such configuration the 32 time_t is always present.  

For __ASSUME_TIME64_SYSCALLS (default fro 64 bit time_t ABI and for 32
bit time_t with --enable-kernel=5.1) the 32 bit syscall should not be
issued.

There are still the issue for a default configured glibc when running
on kernels with CONFIG_COMPAT_32BIT_TIME=y, this would require to remove
the fallback optimizations for !__ASSUME_TIME64_SYSCALLS.
Arnd Bergmann Nov. 8, 2022, 2:07 p.m. UTC | #10
On Tue, Nov 8, 2022, at 14:49, Adhemerval Zanella Netto wrote:
> On 08/11/22 10:27, Arnd Bergmann wrote:
>
> Yes, the 32 bit fallback assumes that you either use the default minimum
> kernel or configure with --enable-kernel with a value lower than 5.1.
> And the optimization such as ecf2661281c was added on the basis that for
> such configuration the 32 time_t is always present.  
>
> For __ASSUME_TIME64_SYSCALLS (default fro 64 bit time_t ABI and for 32
> bit time_t with --enable-kernel=5.1) the 32 bit syscall should not be
> issued.

Ok, good. What is the amount of testing that this combination
(--enable-kernel=5.1, CONFIG_COMPAT_32_BIT_TIME=n) has seen? Is
this something that is already part of some regression test setup,
or rather something that is supposed to work but isn't in
widespread use?

> There are still the issue for a default configured glibc when running
> on kernels with CONFIG_COMPAT_32BIT_TIME=y, this would require to remove
> the fallback optimizations for !__ASSUME_TIME64_SYSCALLS.

You mean CONFIG_COMPAT_32BIT_TIME=n with !__ASSUME_TIME64_SYSCALLS,
right? As I said, I'm not too worried about this corner case, as
long as there is some kind of use feedback that tells users to
change either glibc or kernel configuration.

My impression is that the optimizing for running on old kernels
is not overly helpful, and that changing the fallback logic
would be better, but this does not feel like a correctness
issue when general-purpose distros always enable
CONFIG_COMPAT_32BIT_TIME, and embedded users that want it
disabled always build a matching glibc as well.

      Arnd
Adhemerval Zanella Netto Nov. 8, 2022, 2:27 p.m. UTC | #11
On 08/11/22 11:07, Arnd Bergmann wrote:
> On Tue, Nov 8, 2022, at 14:49, Adhemerval Zanella Netto wrote:
>> On 08/11/22 10:27, Arnd Bergmann wrote:
>>
>> Yes, the 32 bit fallback assumes that you either use the default minimum
>> kernel or configure with --enable-kernel with a value lower than 5.1.
>> And the optimization such as ecf2661281c was added on the basis that for
>> such configuration the 32 time_t is always present.  
>>
>> For __ASSUME_TIME64_SYSCALLS (default fro 64 bit time_t ABI and for 32
>> bit time_t with --enable-kernel=5.1) the 32 bit syscall should not be
>> issued.
> 
> Ok, good. What is the amount of testing that this combination
> (--enable-kernel=5.1, CONFIG_COMPAT_32_BIT_TIME=n) has seen? Is
> this something that is already part of some regression test setup,
> or rather something that is supposed to work but isn't in
> widespread use?

I would say not much I am aware off, I usually check only against stock 
kernels from usual distributions (ubuntu, fedora, etc) and our patchwork 
instance also uses default kernels.

> 
>> There are still the issue for a default configured glibc when running
>> on kernels with CONFIG_COMPAT_32BIT_TIME=y, this would require to remove
>> the fallback optimizations for !__ASSUME_TIME64_SYSCALLS.
> 
> You mean CONFIG_COMPAT_32BIT_TIME=n with !__ASSUME_TIME64_SYSCALLS,
> right? As I said, I'm not too worried about this corner case, as
> long as there is some kind of use feedback that tells users to
> change either glibc or kernel configuration.
> 
> My impression is that the optimizing for running on old kernels
> is not overly helpful, and that changing the fallback logic
> would be better, but this does not feel like a correctness
> issue when general-purpose distros always enable
> CONFIG_COMPAT_32BIT_TIME, and embedded users that want it
> disabled always build a matching glibc as well.

I added the optimization mainly because to disable the use of 32 bit
time_t support requires a configure switch.  It is worries me a bit
the combination of CONFIG_COMPAT_32BIT_TIME=n with 
!__ASSUME_TIME64_SYSCALLS as potential source of obscures bugs, but
I think that it would be unlikely in future when newer kernels will
be more present.
Adhemerval Zanella Netto Nov. 8, 2022, 7:47 p.m. UTC | #12
On 08/11/22 11:27, Adhemerval Zanella Netto wrote:
> 
> 
> On 08/11/22 11:07, Arnd Bergmann wrote:
>> On Tue, Nov 8, 2022, at 14:49, Adhemerval Zanella Netto wrote:
>>> On 08/11/22 10:27, Arnd Bergmann wrote:
>>>
>>> Yes, the 32 bit fallback assumes that you either use the default minimum
>>> kernel or configure with --enable-kernel with a value lower than 5.1.
>>> And the optimization such as ecf2661281c was added on the basis that for
>>> such configuration the 32 time_t is always present.  
>>>
>>> For __ASSUME_TIME64_SYSCALLS (default fro 64 bit time_t ABI and for 32
>>> bit time_t with --enable-kernel=5.1) the 32 bit syscall should not be
>>> issued.
>>
>> Ok, good. What is the amount of testing that this combination
>> (--enable-kernel=5.1, CONFIG_COMPAT_32_BIT_TIME=n) has seen? Is
>> this something that is already part of some regression test setup,
>> or rather something that is supposed to work but isn't in
>> widespread use?
> 
> I would say not much I am aware off, I usually check only against stock 
> kernels from usual distributions (ubuntu, fedora, etc) and our patchwork 
> instance also uses default kernels.
> 
>>
>>> There are still the issue for a default configured glibc when running
>>> on kernels with CONFIG_COMPAT_32BIT_TIME=y, this would require to remove
>>> the fallback optimizations for !__ASSUME_TIME64_SYSCALLS.
>>
>> You mean CONFIG_COMPAT_32BIT_TIME=n with !__ASSUME_TIME64_SYSCALLS,
>> right? As I said, I'm not too worried about this corner case, as
>> long as there is some kind of use feedback that tells users to
>> change either glibc or kernel configuration.
>>
>> My impression is that the optimizing for running on old kernels
>> is not overly helpful, and that changing the fallback logic
>> would be better, but this does not feel like a correctness
>> issue when general-purpose distros always enable
>> CONFIG_COMPAT_32BIT_TIME, and embedded users that want it
>> disabled always build a matching glibc as well.
> 
> I added the optimization mainly because to disable the use of 32 bit
> time_t support requires a configure switch.  It is worries me a bit
> the combination of CONFIG_COMPAT_32BIT_TIME=n with 
> !__ASSUME_TIME64_SYSCALLS as potential source of obscures bugs, but
> I think that it would be unlikely in future when newer kernels will
> be more present.

I am ccing Rich because he agrees that CONFIG_COMPAT_32BIT_TIME is a 
userspace breakage and it will most likely break musl tim64 support.
He suggested to move this option behind EXPERT [1] and fix the 
documentation.

[1] http://ix.io/4bse
Rich Felker Nov. 8, 2022, 11:29 p.m. UTC | #13
On Tue, Nov 08, 2022 at 04:47:06PM -0300, Adhemerval Zanella Netto wrote:
> 
> 
> On 08/11/22 11:27, Adhemerval Zanella Netto wrote:
> > 
> > 
> > On 08/11/22 11:07, Arnd Bergmann wrote:
> >> On Tue, Nov 8, 2022, at 14:49, Adhemerval Zanella Netto wrote:
> >>> On 08/11/22 10:27, Arnd Bergmann wrote:
> >>>
> >>> Yes, the 32 bit fallback assumes that you either use the default minimum
> >>> kernel or configure with --enable-kernel with a value lower than 5.1.
> >>> And the optimization such as ecf2661281c was added on the basis that for
> >>> such configuration the 32 time_t is always present.  
> >>>
> >>> For __ASSUME_TIME64_SYSCALLS (default fro 64 bit time_t ABI and for 32
> >>> bit time_t with --enable-kernel=5.1) the 32 bit syscall should not be
> >>> issued.
> >>
> >> Ok, good. What is the amount of testing that this combination
> >> (--enable-kernel=5.1, CONFIG_COMPAT_32_BIT_TIME=n) has seen? Is
> >> this something that is already part of some regression test setup,
> >> or rather something that is supposed to work but isn't in
> >> widespread use?
> > 
> > I would say not much I am aware off, I usually check only against stock 
> > kernels from usual distributions (ubuntu, fedora, etc) and our patchwork 
> > instance also uses default kernels.
> > 
> >>
> >>> There are still the issue for a default configured glibc when running
> >>> on kernels with CONFIG_COMPAT_32BIT_TIME=y, this would require to remove
> >>> the fallback optimizations for !__ASSUME_TIME64_SYSCALLS.
> >>
> >> You mean CONFIG_COMPAT_32BIT_TIME=n with !__ASSUME_TIME64_SYSCALLS,
> >> right? As I said, I'm not too worried about this corner case, as
> >> long as there is some kind of use feedback that tells users to
> >> change either glibc or kernel configuration.
> >>
> >> My impression is that the optimizing for running on old kernels
> >> is not overly helpful, and that changing the fallback logic
> >> would be better, but this does not feel like a correctness
> >> issue when general-purpose distros always enable
> >> CONFIG_COMPAT_32BIT_TIME, and embedded users that want it
> >> disabled always build a matching glibc as well.
> > 
> > I added the optimization mainly because to disable the use of 32 bit
> > time_t support requires a configure switch.  It is worries me a bit
> > the combination of CONFIG_COMPAT_32BIT_TIME=n with 
> > !__ASSUME_TIME64_SYSCALLS as potential source of obscures bugs, but
> > I think that it would be unlikely in future when newer kernels will
> > be more present.
> 
> I am ccing Rich because he agrees that CONFIG_COMPAT_32BIT_TIME is a 
> userspace breakage and it will most likely break musl tim64 support.
> He suggested to move this option behind EXPERT [1] and fix the 
> documentation.

It's absolutely a violation of the "don't break userspace" syscall
API/ABI stability policy, and *does* break musl. We generally do not
use "new" syscalls except when the "old" syscall lacks the
functionality needed.

Rich
Adhemerval Zanella Netto Nov. 17, 2022, 5:35 p.m. UTC | #14
On 08/11/22 01:49, YunQiang Su wrote:
> Currently glibc uses in_time_t_range to detects time_t overflow,
> and if it occurs fallbacks to 64 bit syscall version.
> 
> The function name is confusing because internally time_t might be
> either 32 bits or 64 bits (depending on __TIMESIZE).
> 
> This patch refactors the in_time_t_range by replacing it with
> in_int32_t_range for the case to check if the 64 bit time_t syscall
> should be used.
> 
> The in_time_t range is used to detect overflow of the
> syscall return value.

LGTM, thanks.  I will install this patch.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
>  include/time.h                            | 10 +++++++++-
>  nptl/futex-internal.c                     |  4 ++--
>  sysdeps/unix/sysv/linux/clock_adjtime.c   |  2 +-
>  sysdeps/unix/sysv/linux/clock_nanosleep.c |  2 +-
>  sysdeps/unix/sysv/linux/clock_settime.c   |  2 +-
>  sysdeps/unix/sysv/linux/mq_timedreceive.c |  2 +-
>  sysdeps/unix/sysv/linux/mq_timedsend.c    |  2 +-
>  sysdeps/unix/sysv/linux/ppoll.c           |  2 +-
>  sysdeps/unix/sysv/linux/pselect.c         |  2 +-
>  sysdeps/unix/sysv/linux/recvmmsg.c        |  2 +-
>  sysdeps/unix/sysv/linux/select.c          |  2 +-
>  sysdeps/unix/sysv/linux/semtimedop.c      |  2 +-
>  sysdeps/unix/sysv/linux/setitimer.c       |  4 ++--
>  sysdeps/unix/sysv/linux/setsockopt.c      |  2 +-
>  sysdeps/unix/sysv/linux/sigtimedwait.c    |  2 +-
>  sysdeps/unix/sysv/linux/timer_settime.c   |  4 ++--
>  sysdeps/unix/sysv/linux/timerfd_settime.c |  4 ++--
>  sysdeps/unix/sysv/linux/utimensat.c       |  4 ++--
>  18 files changed, 31 insertions(+), 23 deletions(-)
> 
> diff --git a/include/time.h b/include/time.h
> index 20abea69d4..f599eeed4e 100644
> --- a/include/time.h
> +++ b/include/time.h
> @@ -347,12 +347,20 @@ libc_hidden_proto (__time64)
>  /* Check whether T fits in int32_t, assume all usages are for
>     sizeof(time_t) == 32.  */
>  static inline bool
> -in_time_t_range (__time64_t t)
> +in_int32_t_range (__time64_t t)
>  {
>    int32_t s = t;
>    return s == t;
>  }
>  
> +/* Check whether T fits in time_t.  */
> +static inline bool
> +in_time_t_range (__time64_t t)
> +{
> +  time_t s = t;
> +  return s == t;
> +}
> +
>  /* Convert a known valid struct timeval into a struct __timespec64.  */
>  static inline struct __timespec64
>  valid_timeval_to_timespec64 (const struct timeval tv)
> diff --git a/nptl/futex-internal.c b/nptl/futex-internal.c
> index 7ec228e8fb..6b8ac2304d 100644
> --- a/nptl/futex-internal.c
> +++ b/nptl/futex-internal.c
> @@ -87,7 +87,7 @@ __futex_abstimed_wait_common (unsigned int* futex_word,
>    err = __futex_abstimed_wait_common64 (futex_word, expected, op, abstime,
>  					private, cancel);
>  #else
> -  bool need_time64 = abstime != NULL && !in_time_t_range (abstime->tv_sec);
> +  bool need_time64 = abstime != NULL && !in_int32_t_range (abstime->tv_sec);
>    if (need_time64)
>      {
>        err = __futex_abstimed_wait_common64 (futex_word, expected, op, abstime,
> @@ -162,7 +162,7 @@ __futex_lock_pi64 (int *futex_word, clockid_t clockid,
>  # ifdef __ASSUME_TIME64_SYSCALLS
>    err = INTERNAL_SYSCALL_CALL (futex_time64, futex_word, op_pi, 0, abstime);
>  # else
> -  bool need_time64 = abstime != NULL && !in_time_t_range (abstime->tv_sec);
> +  bool need_time64 = abstime != NULL && !in_int32_t_range (abstime->tv_sec);
>    if (need_time64)
>      err = INTERNAL_SYSCALL_CALL (futex_time64, futex_word, op_pi, 0, abstime);
>    else
> diff --git a/sysdeps/unix/sysv/linux/clock_adjtime.c b/sysdeps/unix/sysv/linux/clock_adjtime.c
> index 5ded82f506..63ea68c3af 100644
> --- a/sysdeps/unix/sysv/linux/clock_adjtime.c
> +++ b/sysdeps/unix/sysv/linux/clock_adjtime.c
> @@ -35,7 +35,7 @@ __clock_adjtime64 (const clockid_t clock_id, struct __timex64 *tx64)
>      return r;
>  
>    if (tx64->modes & ADJ_SETOFFSET
> -      && ! in_time_t_range (tx64->time.tv_sec))
> +      && ! in_int32_t_range (tx64->time.tv_sec))
>      {
>        __set_errno (EOVERFLOW);
>        return -1;
> diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
> index e610fd4e8d..9031060486 100644
> --- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
> +++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
> @@ -48,7 +48,7 @@ __clock_nanosleep_time64 (clockid_t clock_id, int flags,
>    r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, flags, req,
>  			       rem);
>  #else
> -  if (!in_time_t_range (req->tv_sec))
> +  if (!in_int32_t_range (req->tv_sec))
>      {
>        r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, flags,
>  				   req, rem);
> diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
> index 2a32e2eb13..db9698ba0d 100644
> --- a/sysdeps/unix/sysv/linux/clock_settime.c
> +++ b/sysdeps/unix/sysv/linux/clock_settime.c
> @@ -41,7 +41,7 @@ __clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
>    if (ret == 0 || errno != ENOSYS)
>      return ret;
>  
> -  if (! in_time_t_range (tp->tv_sec))
> +  if (! in_int32_t_range (tp->tv_sec))
>      {
>        __set_errno (EOVERFLOW);
>        return -1;
> diff --git a/sysdeps/unix/sysv/linux/mq_timedreceive.c b/sysdeps/unix/sysv/linux/mq_timedreceive.c
> index 5bf1e0a83b..6c719d4b70 100644
> --- a/sysdeps/unix/sysv/linux/mq_timedreceive.c
> +++ b/sysdeps/unix/sysv/linux/mq_timedreceive.c
> @@ -36,7 +36,7 @@ ___mq_timedreceive_time64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len
>  			 msg_prio, abs_timeout);
>  #else
>    bool need_time64 = abs_timeout != NULL
> -		     && !in_time_t_range (abs_timeout->tv_sec);
> +		     && !in_int32_t_range (abs_timeout->tv_sec);
>    if (need_time64)
>      {
>        int r = SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, msg_len,
> diff --git a/sysdeps/unix/sysv/linux/mq_timedsend.c b/sysdeps/unix/sysv/linux/mq_timedsend.c
> index 3ca5050976..eb8353feef 100644
> --- a/sysdeps/unix/sysv/linux/mq_timedsend.c
> +++ b/sysdeps/unix/sysv/linux/mq_timedsend.c
> @@ -36,7 +36,7 @@ ___mq_timedsend_time64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
>  			 msg_prio, abs_timeout);
>  #else
>    bool need_time64 = abs_timeout != NULL
> -		     && !in_time_t_range (abs_timeout->tv_sec);
> +		     && !in_int32_t_range (abs_timeout->tv_sec);
>    if (need_time64)
>      {
>        int r = SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, msg_len,
> diff --git a/sysdeps/unix/sysv/linux/ppoll.c b/sysdeps/unix/sysv/linux/ppoll.c
> index 1105e29b00..6653e1bc55 100644
> --- a/sysdeps/unix/sysv/linux/ppoll.c
> +++ b/sysdeps/unix/sysv/linux/ppoll.c
> @@ -43,7 +43,7 @@ __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout,
>  			 __NSIG_BYTES);
>  #else
>    int ret;
> -  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
> +  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
>    if (need_time64)
>      {
>        ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
> diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c
> index eba1c111f8..23fd0dfad6 100644
> --- a/sysdeps/unix/sysv/linux/pselect.c
> +++ b/sysdeps/unix/sysv/linux/pselect.c
> @@ -56,7 +56,7 @@ __pselect64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
>    return pselect64_syscall (nfds, readfds, writefds, exceptfds, timeout,
>  			    sigmask);
>  #else
> -  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
> +  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
>    if (need_time64)
>      {
>        int r = pselect64_syscall (nfds, readfds, writefds, exceptfds, timeout,
> diff --git a/sysdeps/unix/sysv/linux/recvmmsg.c b/sysdeps/unix/sysv/linux/recvmmsg.c
> index d9664d61c4..1ba5a4f25c 100644
> --- a/sysdeps/unix/sysv/linux/recvmmsg.c
> +++ b/sysdeps/unix/sysv/linux/recvmmsg.c
> @@ -35,7 +35,7 @@ recvmmsg_syscall (int fd, struct mmsghdr *vmessages, unsigned int vlen,
>    struct timespec ts32, *pts32 = NULL;
>    if (timeout != NULL)
>      {
> -      if (! in_time_t_range (timeout->tv_sec))
> +      if (! in_int32_t_range (timeout->tv_sec))
>  	{
>  	  __set_errno (EINVAL);
>  	  return -1;
> diff --git a/sysdeps/unix/sysv/linux/select.c b/sysdeps/unix/sysv/linux/select.c
> index a3f0a2eba7..fd147dfdd4 100644
> --- a/sysdeps/unix/sysv/linux/select.c
> +++ b/sysdeps/unix/sysv/linux/select.c
> @@ -72,7 +72,7 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
>      TIMESPEC_TO_TIMEVAL (timeout, pts64);
>    return r;
>  #else
> -  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
> +  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
>    if (need_time64)
>      {
>        int r = SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds,
> diff --git a/sysdeps/unix/sysv/linux/semtimedop.c b/sysdeps/unix/sysv/linux/semtimedop.c
> index 38a401bb6f..0cdc0fad4b 100644
> --- a/sysdeps/unix/sysv/linux/semtimedop.c
> +++ b/sysdeps/unix/sysv/linux/semtimedop.c
> @@ -42,7 +42,7 @@ __semtimedop64 (int semid, struct sembuf *sops, size_t nsops,
>  #ifdef __ASSUME_TIME64_SYSCALLS
>    return semtimedop_syscall (semid, sops, nsops, timeout);
>  #else
> -  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
> +  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
>    if (need_time64)
>      {
>        int r = semtimedop_syscall (semid, sops, nsops, timeout);
> diff --git a/sysdeps/unix/sysv/linux/setitimer.c b/sysdeps/unix/sysv/linux/setitimer.c
> index 6d5183aa63..55e6003e0f 100644
> --- a/sysdeps/unix/sysv/linux/setitimer.c
> +++ b/sysdeps/unix/sysv/linux/setitimer.c
> @@ -32,8 +32,8 @@ __setitimer64 (__itimer_which_t which,
>  #else
>    struct __itimerval32 new_value_32;
>  
> -  if (! in_time_t_range (new_value->it_interval.tv_sec)
> -      || ! in_time_t_range (new_value->it_value.tv_sec))
> +  if (! in_int32_t_range (new_value->it_interval.tv_sec)
> +      || ! in_int32_t_range (new_value->it_value.tv_sec))
>      {
>        __set_errno (EOVERFLOW);
>        return -1;
> diff --git a/sysdeps/unix/sysv/linux/setsockopt.c b/sysdeps/unix/sysv/linux/setsockopt.c
> index 4292f411f3..6506ca03ab 100644
> --- a/sysdeps/unix/sysv/linux/setsockopt.c
> +++ b/sysdeps/unix/sysv/linux/setsockopt.c
> @@ -54,7 +54,7 @@ setsockopt32 (int fd, int level, int optname, const void *optval,
>  	  }
>  
>  	struct __timeval64 *tv64 = (struct __timeval64 *) optval;
> -	if (! in_time_t_range (tv64->tv_sec))
> +	if (! in_int32_t_range (tv64->tv_sec))
>  	  {
>  	    __set_errno (EOVERFLOW);
>  	    break;
> diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
> index 069fa1d5e4..1993e3f85a 100644
> --- a/sysdeps/unix/sysv/linux/sigtimedwait.c
> +++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
> @@ -31,7 +31,7 @@ __sigtimedwait64 (const sigset_t *set, siginfo_t *info,
>    result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, timeout,
>  			   __NSIG_BYTES);
>  #else
> -  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
> +  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
>    if (need_time64)
>      {
>        result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, timeout,
> diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
> index 518fed9c59..056e0aff59 100644
> --- a/sysdeps/unix/sysv/linux/timer_settime.c
> +++ b/sysdeps/unix/sysv/linux/timer_settime.c
> @@ -46,8 +46,8 @@ ___timer_settime64 (timer_t timerid, int flags,
>  #  endif
>    struct itimerspec its32, oits32;
>  
> -  if (! in_time_t_range ((value->it_value).tv_sec)
> -      || ! in_time_t_range ((value->it_interval).tv_sec))
> +  if (! in_int32_t_range ((value->it_value).tv_sec)
> +      || ! in_int32_t_range ((value->it_interval).tv_sec))
>      {
>        __set_errno (EOVERFLOW);
>        return -1;
> diff --git a/sysdeps/unix/sysv/linux/timerfd_settime.c b/sysdeps/unix/sysv/linux/timerfd_settime.c
> index 59282bf1ad..c5f3f14c3b 100644
> --- a/sysdeps/unix/sysv/linux/timerfd_settime.c
> +++ b/sysdeps/unix/sysv/linux/timerfd_settime.c
> @@ -33,8 +33,8 @@ __timerfd_settime64 (int fd, int flags, const struct __itimerspec64 *value,
>  #ifdef __ASSUME_TIME64_SYSCALLS
>    return INLINE_SYSCALL_CALL (timerfd_settime64, fd, flags, value, ovalue);
>  #else
> -  bool need_time64 = !in_time_t_range (value->it_value.tv_sec)
> -		     || !in_time_t_range (value->it_interval.tv_sec);
> +  bool need_time64 = !in_int32_t_range (value->it_value.tv_sec)
> +		     || !in_int32_t_range (value->it_interval.tv_sec);
>    if (need_time64)
>      {
>        int r = INLINE_SYSCALL_CALL (timerfd_settime64, fd, flags, value,
> diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
> index 5662ecc9aa..54a5e47618 100644
> --- a/sysdeps/unix/sysv/linux/utimensat.c
> +++ b/sysdeps/unix/sysv/linux/utimensat.c
> @@ -41,9 +41,9 @@ __utimensat64_helper (int fd, const char *file,
>  
>    bool need_time64 = tsp64 != NULL
>  		     && ((!TS_SPECIAL (tsp64[0])
> -			  && !in_time_t_range (tsp64[0].tv_sec))
> +			  && !in_int32_t_range (tsp64[0].tv_sec))
>  			 || (!TS_SPECIAL (tsp64[1])
> -			     && !in_time_t_range (tsp64[1].tv_sec)));
> +			     && !in_int32_t_range (tsp64[1].tv_sec)));
>    if (need_time64)
>      {
>        int r = INLINE_SYSCALL_CALL (utimensat_time64, fd, file, &tsp64[0],
diff mbox series

Patch

diff --git a/include/time.h b/include/time.h
index 20abea69d4..f599eeed4e 100644
--- a/include/time.h
+++ b/include/time.h
@@ -347,12 +347,20 @@  libc_hidden_proto (__time64)
 /* Check whether T fits in int32_t, assume all usages are for
    sizeof(time_t) == 32.  */
 static inline bool
-in_time_t_range (__time64_t t)
+in_int32_t_range (__time64_t t)
 {
   int32_t s = t;
   return s == t;
 }
 
+/* Check whether T fits in time_t.  */
+static inline bool
+in_time_t_range (__time64_t t)
+{
+  time_t s = t;
+  return s == t;
+}
+
 /* Convert a known valid struct timeval into a struct __timespec64.  */
 static inline struct __timespec64
 valid_timeval_to_timespec64 (const struct timeval tv)
diff --git a/nptl/futex-internal.c b/nptl/futex-internal.c
index 7ec228e8fb..6b8ac2304d 100644
--- a/nptl/futex-internal.c
+++ b/nptl/futex-internal.c
@@ -87,7 +87,7 @@  __futex_abstimed_wait_common (unsigned int* futex_word,
   err = __futex_abstimed_wait_common64 (futex_word, expected, op, abstime,
 					private, cancel);
 #else
-  bool need_time64 = abstime != NULL && !in_time_t_range (abstime->tv_sec);
+  bool need_time64 = abstime != NULL && !in_int32_t_range (abstime->tv_sec);
   if (need_time64)
     {
       err = __futex_abstimed_wait_common64 (futex_word, expected, op, abstime,
@@ -162,7 +162,7 @@  __futex_lock_pi64 (int *futex_word, clockid_t clockid,
 # ifdef __ASSUME_TIME64_SYSCALLS
   err = INTERNAL_SYSCALL_CALL (futex_time64, futex_word, op_pi, 0, abstime);
 # else
-  bool need_time64 = abstime != NULL && !in_time_t_range (abstime->tv_sec);
+  bool need_time64 = abstime != NULL && !in_int32_t_range (abstime->tv_sec);
   if (need_time64)
     err = INTERNAL_SYSCALL_CALL (futex_time64, futex_word, op_pi, 0, abstime);
   else
diff --git a/sysdeps/unix/sysv/linux/clock_adjtime.c b/sysdeps/unix/sysv/linux/clock_adjtime.c
index 5ded82f506..63ea68c3af 100644
--- a/sysdeps/unix/sysv/linux/clock_adjtime.c
+++ b/sysdeps/unix/sysv/linux/clock_adjtime.c
@@ -35,7 +35,7 @@  __clock_adjtime64 (const clockid_t clock_id, struct __timex64 *tx64)
     return r;
 
   if (tx64->modes & ADJ_SETOFFSET
-      && ! in_time_t_range (tx64->time.tv_sec))
+      && ! in_int32_t_range (tx64->time.tv_sec))
     {
       __set_errno (EOVERFLOW);
       return -1;
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index e610fd4e8d..9031060486 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -48,7 +48,7 @@  __clock_nanosleep_time64 (clockid_t clock_id, int flags,
   r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, flags, req,
 			       rem);
 #else
-  if (!in_time_t_range (req->tv_sec))
+  if (!in_int32_t_range (req->tv_sec))
     {
       r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, clock_id, flags,
 				   req, rem);
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index 2a32e2eb13..db9698ba0d 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -41,7 +41,7 @@  __clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
   if (ret == 0 || errno != ENOSYS)
     return ret;
 
-  if (! in_time_t_range (tp->tv_sec))
+  if (! in_int32_t_range (tp->tv_sec))
     {
       __set_errno (EOVERFLOW);
       return -1;
diff --git a/sysdeps/unix/sysv/linux/mq_timedreceive.c b/sysdeps/unix/sysv/linux/mq_timedreceive.c
index 5bf1e0a83b..6c719d4b70 100644
--- a/sysdeps/unix/sysv/linux/mq_timedreceive.c
+++ b/sysdeps/unix/sysv/linux/mq_timedreceive.c
@@ -36,7 +36,7 @@  ___mq_timedreceive_time64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len
 			 msg_prio, abs_timeout);
 #else
   bool need_time64 = abs_timeout != NULL
-		     && !in_time_t_range (abs_timeout->tv_sec);
+		     && !in_int32_t_range (abs_timeout->tv_sec);
   if (need_time64)
     {
       int r = SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, msg_len,
diff --git a/sysdeps/unix/sysv/linux/mq_timedsend.c b/sysdeps/unix/sysv/linux/mq_timedsend.c
index 3ca5050976..eb8353feef 100644
--- a/sysdeps/unix/sysv/linux/mq_timedsend.c
+++ b/sysdeps/unix/sysv/linux/mq_timedsend.c
@@ -36,7 +36,7 @@  ___mq_timedsend_time64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
 			 msg_prio, abs_timeout);
 #else
   bool need_time64 = abs_timeout != NULL
-		     && !in_time_t_range (abs_timeout->tv_sec);
+		     && !in_int32_t_range (abs_timeout->tv_sec);
   if (need_time64)
     {
       int r = SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, msg_len,
diff --git a/sysdeps/unix/sysv/linux/ppoll.c b/sysdeps/unix/sysv/linux/ppoll.c
index 1105e29b00..6653e1bc55 100644
--- a/sysdeps/unix/sysv/linux/ppoll.c
+++ b/sysdeps/unix/sysv/linux/ppoll.c
@@ -43,7 +43,7 @@  __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout,
 			 __NSIG_BYTES);
 #else
   int ret;
-  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
+  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
   if (need_time64)
     {
       ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c
index eba1c111f8..23fd0dfad6 100644
--- a/sysdeps/unix/sysv/linux/pselect.c
+++ b/sysdeps/unix/sysv/linux/pselect.c
@@ -56,7 +56,7 @@  __pselect64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
   return pselect64_syscall (nfds, readfds, writefds, exceptfds, timeout,
 			    sigmask);
 #else
-  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
+  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
   if (need_time64)
     {
       int r = pselect64_syscall (nfds, readfds, writefds, exceptfds, timeout,
diff --git a/sysdeps/unix/sysv/linux/recvmmsg.c b/sysdeps/unix/sysv/linux/recvmmsg.c
index d9664d61c4..1ba5a4f25c 100644
--- a/sysdeps/unix/sysv/linux/recvmmsg.c
+++ b/sysdeps/unix/sysv/linux/recvmmsg.c
@@ -35,7 +35,7 @@  recvmmsg_syscall (int fd, struct mmsghdr *vmessages, unsigned int vlen,
   struct timespec ts32, *pts32 = NULL;
   if (timeout != NULL)
     {
-      if (! in_time_t_range (timeout->tv_sec))
+      if (! in_int32_t_range (timeout->tv_sec))
 	{
 	  __set_errno (EINVAL);
 	  return -1;
diff --git a/sysdeps/unix/sysv/linux/select.c b/sysdeps/unix/sysv/linux/select.c
index a3f0a2eba7..fd147dfdd4 100644
--- a/sysdeps/unix/sysv/linux/select.c
+++ b/sysdeps/unix/sysv/linux/select.c
@@ -72,7 +72,7 @@  __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
     TIMESPEC_TO_TIMEVAL (timeout, pts64);
   return r;
 #else
-  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
+  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
   if (need_time64)
     {
       int r = SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds,
diff --git a/sysdeps/unix/sysv/linux/semtimedop.c b/sysdeps/unix/sysv/linux/semtimedop.c
index 38a401bb6f..0cdc0fad4b 100644
--- a/sysdeps/unix/sysv/linux/semtimedop.c
+++ b/sysdeps/unix/sysv/linux/semtimedop.c
@@ -42,7 +42,7 @@  __semtimedop64 (int semid, struct sembuf *sops, size_t nsops,
 #ifdef __ASSUME_TIME64_SYSCALLS
   return semtimedop_syscall (semid, sops, nsops, timeout);
 #else
-  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
+  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
   if (need_time64)
     {
       int r = semtimedop_syscall (semid, sops, nsops, timeout);
diff --git a/sysdeps/unix/sysv/linux/setitimer.c b/sysdeps/unix/sysv/linux/setitimer.c
index 6d5183aa63..55e6003e0f 100644
--- a/sysdeps/unix/sysv/linux/setitimer.c
+++ b/sysdeps/unix/sysv/linux/setitimer.c
@@ -32,8 +32,8 @@  __setitimer64 (__itimer_which_t which,
 #else
   struct __itimerval32 new_value_32;
 
-  if (! in_time_t_range (new_value->it_interval.tv_sec)
-      || ! in_time_t_range (new_value->it_value.tv_sec))
+  if (! in_int32_t_range (new_value->it_interval.tv_sec)
+      || ! in_int32_t_range (new_value->it_value.tv_sec))
     {
       __set_errno (EOVERFLOW);
       return -1;
diff --git a/sysdeps/unix/sysv/linux/setsockopt.c b/sysdeps/unix/sysv/linux/setsockopt.c
index 4292f411f3..6506ca03ab 100644
--- a/sysdeps/unix/sysv/linux/setsockopt.c
+++ b/sysdeps/unix/sysv/linux/setsockopt.c
@@ -54,7 +54,7 @@  setsockopt32 (int fd, int level, int optname, const void *optval,
 	  }
 
 	struct __timeval64 *tv64 = (struct __timeval64 *) optval;
-	if (! in_time_t_range (tv64->tv_sec))
+	if (! in_int32_t_range (tv64->tv_sec))
 	  {
 	    __set_errno (EOVERFLOW);
 	    break;
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index 069fa1d5e4..1993e3f85a 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -31,7 +31,7 @@  __sigtimedwait64 (const sigset_t *set, siginfo_t *info,
   result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, timeout,
 			   __NSIG_BYTES);
 #else
-  bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
+  bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
   if (need_time64)
     {
       result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, timeout,
diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
index 518fed9c59..056e0aff59 100644
--- a/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/sysdeps/unix/sysv/linux/timer_settime.c
@@ -46,8 +46,8 @@  ___timer_settime64 (timer_t timerid, int flags,
 #  endif
   struct itimerspec its32, oits32;
 
-  if (! in_time_t_range ((value->it_value).tv_sec)
-      || ! in_time_t_range ((value->it_interval).tv_sec))
+  if (! in_int32_t_range ((value->it_value).tv_sec)
+      || ! in_int32_t_range ((value->it_interval).tv_sec))
     {
       __set_errno (EOVERFLOW);
       return -1;
diff --git a/sysdeps/unix/sysv/linux/timerfd_settime.c b/sysdeps/unix/sysv/linux/timerfd_settime.c
index 59282bf1ad..c5f3f14c3b 100644
--- a/sysdeps/unix/sysv/linux/timerfd_settime.c
+++ b/sysdeps/unix/sysv/linux/timerfd_settime.c
@@ -33,8 +33,8 @@  __timerfd_settime64 (int fd, int flags, const struct __itimerspec64 *value,
 #ifdef __ASSUME_TIME64_SYSCALLS
   return INLINE_SYSCALL_CALL (timerfd_settime64, fd, flags, value, ovalue);
 #else
-  bool need_time64 = !in_time_t_range (value->it_value.tv_sec)
-		     || !in_time_t_range (value->it_interval.tv_sec);
+  bool need_time64 = !in_int32_t_range (value->it_value.tv_sec)
+		     || !in_int32_t_range (value->it_interval.tv_sec);
   if (need_time64)
     {
       int r = INLINE_SYSCALL_CALL (timerfd_settime64, fd, flags, value,
diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
index 5662ecc9aa..54a5e47618 100644
--- a/sysdeps/unix/sysv/linux/utimensat.c
+++ b/sysdeps/unix/sysv/linux/utimensat.c
@@ -41,9 +41,9 @@  __utimensat64_helper (int fd, const char *file,
 
   bool need_time64 = tsp64 != NULL
 		     && ((!TS_SPECIAL (tsp64[0])
-			  && !in_time_t_range (tsp64[0].tv_sec))
+			  && !in_int32_t_range (tsp64[0].tv_sec))
 			 || (!TS_SPECIAL (tsp64[1])
-			     && !in_time_t_range (tsp64[1].tv_sec)));
+			     && !in_int32_t_range (tsp64[1].tv_sec)));
   if (need_time64)
     {
       int r = INLINE_SYSCALL_CALL (utimensat_time64, fd, file, &tsp64[0],