From a9acb7b39ed21386142b963aeecc35e0b468c0de Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Tue, 8 Nov 2022 12:49:46 +0800 Subject: Define in_int32_t_range to check if the 64 bit time_t syscall should be used 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. Reviewed-by: Adhemerval Zanella --- 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 20abea6..f599eee 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 7ec228e..6b8ac23 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 5ded82f..63ea68c 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 e610fd4..9031060 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 2a32e2e..db9698b 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 5bf1e0a..6c719d4 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 3ca5050..eb8353f 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 2e173b9..45b52d6 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 eba1c11..23fd0df 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 d9664d6..1ba5a4f 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 a3f0a2e..fd147df 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 38a401b..0cdc0fa 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 6d5183a..55e6003 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 4292f41..6506ca0 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 069fa1d..1993e3f 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 518fed9..056e0af 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 59282bf..c5f3f14 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 5662ecc..54a5e47 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], -- cgit v1.1