Bug 29084 - The fix for glibc y2038 may have a mechanism bug.
Summary: The fix for glibc y2038 may have a mechanism bug.
Status: RESOLVED NOTABUG
Alias: None
Product: glibc
Classification: Unclassified
Component: time (show other bugs)
Version: 2.36
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-04-22 06:55 UTC by nixiaoming
Modified: 2022-04-23 13:41 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description nixiaoming 2022-04-22 06:55:02 UTC
Y2038 issue: Use 32-bit timestamps to store, overflow occurs in 2038.
To fix the Y2038 issue, the 64-bit save time needs to be used. A large number of system calls are added to the corresponding community,
However, to ensure compatibility, the original interface still exists,

In the Y2038 patch ,  the modification scheme for these original interfaces is as follows:
Step 1: Convert 32-bit data to 64-bit data.
Step 2: Invoke the new system call (64-bit).
Step 3: Convert the returned data into 32-bit data.

This function is normal in normal scenarios.
However, there is a bug in the case of abnormal input.

case 1: the input address is unreadable and an expected failure is returned. 
    However, in step 1, SIG11 is triggered and the program crashes.
Case 2: The input address is unwritable and an expected failure is returned. 
    However, in step 3, SIG11 is triggered and the program crashes.

According to the preliminary check, the following 69 interfaces may be affected by the logic: 
adjtime
adjtimex
clock_adjtime
clock_getres
clock_gettime
clock_nanosleep
clock_settime
cnd_timedwait
ctime
ctime_r
fstat
fstatat
futimens
futimes
futimesat
getitimer
getrusage
gettimeofday
gmtime
gmtime_r
localtime
localtime_r
lutimes
mktime
msgctl
mtx_timedlock
nanosleep
ntp_gettime
ntp_gettimex
ppoll
pselect
pthread_clockjoin_np
pthread_cond_clockwait
pthread_cond_timedwait
pthread_mutex_clocklock
pthread_mutex_timedlock
pthread_rwlock_clockrdlock
pthread_rwlock_clockwrlock
pthread_rwlock_timedrdlock
pthread_rwlock_timedwrlock
pthread_timedjoin_np
recvmmsg
sched_rr_get_interval
select
sem_clockwait
semctl
semtimedop
sem_timedwait
setitimer
settimeofday
shmctl
sigtimedwait
stat
thrd_sleep
timegm
timerfd_gettime
timerfd_settime
timespec_get
utime
utimensat
utimes
wait3
wait4
aio_suspend
mq_timedreceive
mq_timedsend
timer_gettime
timer_settime
gai_suspend


----
This problem was discovered and reported by the following developers
Xiaoming Ni <nixiaoming@huawei.com>;
huangzhilong <huangzhilong3@h-partners.com>;
liminqiang <liminqiang1@h-partners.com>;
xiaojiangfeng <xiaojiangfeng@huawei.com>;
Comment 1 Adhemerval Zanella 2022-04-22 23:32:23 UTC
(In reply to nixiaoming from comment #0)
> Y2038 issue: Use 32-bit timestamps to store, overflow occurs in 2038.
> To fix the Y2038 issue, the 64-bit save time needs to be used. A large
> number of system calls are added to the corresponding community,
> However, to ensure compatibility, the original interface still exists,
> 
> In the Y2038 patch ,  the modification scheme for these original interfaces
> is as follows:
> Step 1: Convert 32-bit data to 64-bit data.
> Step 2: Invoke the new system call (64-bit).
> Step 3: Convert the returned data into 32-bit data.
> 
> This function is normal in normal scenarios.
> However, there is a bug in the case of abnormal input.
> 
> case 1: the input address is unreadable and an expected failure is returned. 
>     However, in step 1, SIG11 is triggered and the program crashes.
> Case 2: The input address is unwritable and an expected failure is returned. 
>     However, in step 3, SIG11 is triggered and the program crashes.

This is similar to BZ#27662, where as Andreas Schwab has put, it is undefined behavior.  Different than kernel, we don't have a reliable way to generate EFAULT in userland (not without a lot of hacks that it is outside the glibc scope).

A valid issue with the interface is where the contract that state the input *might* be NULL.  In this case, it is invalid the glibc wrapper to assume pointer validity and thus need to handle it (for instance, the timeout input on select).

So as for BZ#27662 I will close this bug a NOTABUG.
Comment 2 nixiaoming 2022-04-23 10:02:41 UTC
Would it be better to add __nonnull to the function declaration?

Like this:

-extern int __adjtimex (struct timex *__ntx);
+extern int __adjtimex (struct timex *__ntx) __nonnull ((1));
Comment 3 Adhemerval Zanella 2022-04-23 13:41:02 UTC
(In reply to nixiaoming from comment #2)
> Would it be better to add __nonnull to the function declaration?
> 
> Like this:
> 
> -extern int __adjtimex (struct timex *__ntx);
> +extern int __adjtimex (struct timex *__ntx) __nonnull ((1));

Yes, this will be a good improvement.  There are multiple interfaces that might be improved with the annotation.