PROBLEM: monotonic clock going backwards on ppc64
flat view
From: Jakub Drnec <hidden>
Date: 2019-02-26 20:36:29
Hi all, I think I observed a potential problem, is this the correct place to report it? (CC me, not on list) [1.] One line summary: monotonic clock can be made to decrease on ppc64 [2.] Full description: Setting the realtime clock can sometimes make the monotonic clock go back by over a hundred years. Decreasing the realtime clock across the y2k38 threshold is one reliable way to reproduce. Allegedly this can also happen just by running ntpd, I have not managed to reproduce that other than booting with rtc at >2038 and then running ntp. When this happens, anything with timers (e.g. openjdk) breaks rather badly. [3.] Keywords: gettimeofday, ppc64, vdso [4.] Kernel information [4.1.] Kernel version: any (tested on 4.19) [4.2.] Kernel .config file: any [5.] Most recent kernel version which did not have the bug: not a regression [6.] Output of Oops..: not applicable [7.] Example program which triggers the problem
--- testcase.c#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
long get_time() {
struct timespec tp;
if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0) {
perror("clock_gettime failed");
exit(1);
}
long result = tp.tv_sec + tp.tv_nsec / 1000000000;
return result;
}
int main() {
printf("monitoring monotonic clock...\n");
long last = get_time();
while(1) {
long now = get_time();
if (now < last) {
printf("clock went backwards by %ld seconds!\n",
last - now);
}
last = now;
sleep(1);
}
return 0;
}
---
when running
# date -s 2040-1-1
# date -s 2037-1-1
program outputs: clock went backwards by 4294967295 seconds!
[8.] Environment: any ppc64, currently reproducing on qemu-system-ppc64le running debian unstable
[X.] Other notes, patches, fixes, workarounds:
The problem seems to be in vDSO code in arch/powerpc/kernel/vdso64/gettimeofday.S.
(possibly because some values used in the calculation are only 32 bit?)
Slightly silly workaround:
nuke the "cmpwi cr1,r3,CLOCK_MONOTONIC" in __kernel_clock_gettime
Now it always goes through the syscall fallback which does not have the same problem.
Regards,
Jakub Drnec