Skip to content

Commit f5807b0

Browse files
Marcelo DalmasKAGA-KOKO
Marcelo Dalmas
authored andcommitted
ntp: Remove invalid cast in time offset math
Due to an unsigned cast, adjtimex() returns the wrong offest when using ADJ_MICRO and the offset is negative. In this case a small negative offset returns approximately 4.29 seconds (~ 2^32/1000 milliseconds) due to the unsigned cast of the negative offset. This cast was added when the kernel internal struct timex was changed to use type long long for the time offset value to address the problem of a 64bit/32bit division on 32bit systems. The correct cast would have been (s32), which is correct as time_offset can only be in the range of [INT_MIN..INT_MAX] because the shift constant used for calculating it is 32. But that's non-obvious. Remove the cast and use div_s64() to cure the issue. [ tglx: Fix white space damage, use div_s64() and amend the change log ] Fixes: ead2541 ("timex: use __kernel_timex internally") Signed-off-by: Marcelo Dalmas <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/all/SJ0P101MB03687BF7D5A10FD3C49C51E5F42E2@SJ0P101MB0368.NAMP101.PROD.OUTLOOK.COM
1 parent 7eef7e3 commit f5807b0

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

kernel/time/ntp.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
798798

799799
txc->offset = shift_right(ntpdata->time_offset * NTP_INTERVAL_FREQ, NTP_SCALE_SHIFT);
800800
if (!(ntpdata->time_status & STA_NANO))
801-
txc->offset = (u32)txc->offset / NSEC_PER_USEC;
801+
txc->offset = div_s64(txc->offset, NSEC_PER_USEC);
802802
}
803803

804804
result = ntpdata->time_state;

0 commit comments

Comments
 (0)