Created attachment 304012 [details] Test program for reproduction Kernel maintains time_offset in scaled nanoseconds in ntp.c. When returning the offset in adjtimex, if ntp state machine has been initialized to operate in microseconds, it divides the offset by 1000 and returns it. Before dividing it seems to be casting it to u32. After division, the new offset can easily fit into positive range of an int64 and hence it is returned as is. This doesn't affect the functionality of ntp kernel routine as time_offset is still correctly maintained in signed nanoseconds but the user gets an incorrect view of the offset. int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts, s32 *time_tai, struct audit_ntp_data *ad) { ... txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, NTP_SCALE_SHIFT); if (!(time_status & STA_NANO)) txc->offset = (u32)txc->offset / NSEC_PER_USEC; <======= } ... } Attached a simple program (adjtimex_test.c) to reproduce, and following is the output: gcc adjtimex_test.c -o adjtimex_test sudo ./adjtimex_test -------------------- Setting offset to 20 offset 20 freq 5082194 maxerror 54471 esterror 1671 status 1 constant 7 precision 1 tolerance 32768000 tick 10000 Setting offset to -15 offset 4294952 freq 5082194 maxerror 54471 esterror 1671 status 1 constant 7 precision 1 tolerance 32768000 tick 10000