linux-test-project / ltp

Linux Test Project (mailing list: https://lists.linux.it/listinfo/ltp)
https://linux-test-project.readthedocs.io/
GNU General Public License v2.0
2.28k stars 1k forks source link

timer_settime03: fails with 5.10.104 kernel on slow ARM device #925

Closed multiple1 closed 2 years ago

multiple1 commented 2 years ago

Hello!

Setup: Kernel 5.10.104 preempt_rt on slow ARM926EJ-S rev 5 (v5l) platform timer_settime03 fails every time, but CVE-2018-12896 should be fixed in 5.10.104 kernel... Maybe some timing issues? Test not reliable on slow platforms?

timer_settime03
/lib/tst_kconfig.c:64: TINFO: Parsing kernel config '/proc/config.gz'
/lib/tst_test.c:1261: TINFO: Timeout per run is 0h 05m 00s
/testcases/kernel/syscalls/timer_settime/timer_settime03.c:105: TFAIL: Timer overrun counter is wrong: 3068; expected 2147483647 or negative number

HINT: You _MAY_ be missing kernel fixes, see:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=78c9c4dfbf8c

HINT: You _MAY_ be vulnerable to CVE(s), see:

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12896
metan-ucw commented 2 years ago

Hmm, the test checks for CONFIG_HIGH_RES_TIMERS=y in the kernel config, but I guess that on embedded hardware without the respective timers in hardware the CLOCK_REALTIME resolution may not be good enough. What is the timer resolution on this board (i.e. what clock_getres(CLOCK_REALTIME, &res) fills into the res structure)?

multiple1 commented 2 years ago

CONFIG_HIGH_RES_TIMERS is enabled in the kernel.

clock_getres(CLOCK_REALTIME, &res) returns: Timer resolution 0 s 1000000 ns

metan-ucw commented 2 years ago

That's 1ms resolution which means that the kernel uses jiffies and there is no high resolution timer hardware present, which means that we do not get enough overflows for the overflow counter to get anywhere close to INT_MAX since the timer interval is set to 1ns as high resolution timers on a machine where the test passes have resolution 1ns.

Maybe we can just scale the timer interval by the timer resolution with following patch:

iff --git a/testcases/kernel/syscalls/timer_settime/timer_settime03.c b/testcases/kernel/syscalls/timer_settime/timer_settime03.c
index 4597bf74e..0c540a0d5 100644
--- a/testcases/kernel/syscalls/timer_settime/timer_settime03.c
+++ b/testcases/kernel/syscalls/timer_settime/timer_settime03.c
@@ -32,6 +32,8 @@
 static timer_t timer;
 static volatile int handler_called, overrun, saved_errno;

+struct timespec resolution;
+
 static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
 {
        struct itimerspec spec;
@@ -46,6 +48,7 @@ static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
        errno = 0;
        overrun = timer_getoverrun(timer);
        saved_errno = errno;
+
        memset(&spec, 0, sizeof(struct itimerspec));
        SAFE_TIMER_SETTIME(timer, 0, &spec, NULL);
        handler_called = 1;
@@ -61,6 +64,11 @@ static void setup(void)

        SAFE_SIGNAL(SIGUSR1, sighandler);
        SAFE_TIMER_CREATE(CLOCK_REALTIME, &sev, &timer);
+
+       SAFE_CLOCK_GETRES(CLOCK_REALTIME, &resolution);
+
+       tst_res(TINFO, "CLOCK_REALTIME resolution %lins",
+               (long)resolution.tv_nsec);
 }

 static void run(void)
@@ -81,9 +89,9 @@ static void run(void)

        /* spec.it_value = now - 1.4 * max overrun value */
        /* IOW, overflow will land right in the middle of negative range */
-       spec.it_value.tv_sec -= handler_delay / 100000000;
+       spec.it_value.tv_sec -= (handler_delay / 100000000) * resolution.tv_nsec;
        spec.it_value.tv_nsec -= nsec;
-       spec.it_interval.tv_nsec = 1;
+       spec.it_interval.tv_nsec = resolution.tv_nsec;

        SAFE_TIMER_SETTIME(timer, TIMER_ABSTIME, &spec, NULL);
        while (!handler_called);
multiple1 commented 2 years ago

Seems to work. I will check the modified test against kernel 3.x.y on same platform next week.

timer_settime03
tst_test.c:1261: TINFO: Timeout per run is 0h 05m 00s
timer_settime03.c:69: TINFO: CLOCK_REALTIME resolution 1000000ns
timer_settime03.c:103: TPASS: Timer overrun count is capped
multiple1 commented 2 years ago

Checked timer_settime03 with your patch against 3.x.y kernel with similar config as the 5.10 kernel => Test fails as expected

./timer_settime03
/lib/tst_test.c:1261: TINFO: Timeout per run is 0h 05m 00s
/testcases/kernel/syscalls/timer_settime/timer_settime03.c:69: TINFO: CLOCK_REALTIME resolution 1000000ns
/testcases/kernel/syscalls/timer_settime/timer_settime03.c:108: TFAIL: Timer overrun counter overflow