Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/timers: Add set-2038 test from timetest suite

Adds the set-2038 test which sets the time to near-edge cases
like the start and end of the 32 bit epoch and checks that
time behaves properly. There is also a dangerous mode, which
lets the clock roll over past 2038 on 32bit systems, which
on some older kernels will cause system hangs.

Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Tested-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>

authored by

John Stultz and committed by
Shuah Khan
0d02a753 3a92a15f

+146 -1
+2 -1
tools/testing/selftests/timers/Makefile
··· 5 5 bins = posix_timers nanosleep inconsistency-check nsleep-lat raw_skew \ 6 6 set-timer-lat threadtest mqueue-lat valid-adjtimex \ 7 7 alarmtimer-suspend change_skew skew_consistency clocksource-switch \ 8 - leap-a-day leapcrash set-tai 8 + leap-a-day leapcrash set-tai set-2038 9 9 10 10 all: ${bins} 11 11 ··· 33 33 ./leap-a-day -s -i 10 34 34 ./leapcrash 35 35 ./set-tai 36 + ./set-2038 36 37 37 38 clean: 38 39 rm -f ${bins}
+144
tools/testing/selftests/timers/set-2038.c
··· 1 + /* Time bounds setting test 2 + * by: john stultz (johnstul@us.ibm.com) 3 + * (C) Copyright IBM 2012 4 + * Licensed under the GPLv2 5 + * 6 + * NOTE: This is a meta-test which sets the time to edge cases then 7 + * uses other tests to detect problems. Thus this test requires that 8 + * the inconsistency-check and nanosleep tests be present in the same 9 + * directory it is run from. 10 + * 11 + * To build: 12 + * $ gcc set-2038.c -o set-2038 -lrt 13 + * 14 + * This program is free software: you can redistribute it and/or modify 15 + * it under the terms of the GNU General Public License as published by 16 + * the Free Software Foundation, either version 2 of the License, or 17 + * (at your option) any later version. 18 + * 19 + * This program is distributed in the hope that it will be useful, 20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 + * GNU General Public License for more details. 23 + */ 24 + 25 + #include <stdio.h> 26 + #include <stdlib.h> 27 + #include <unistd.h> 28 + #include <time.h> 29 + #include <sys/time.h> 30 + #ifdef KTEST 31 + #include "../kselftest.h" 32 + #else 33 + static inline int ksft_exit_pass(void) 34 + { 35 + exit(0); 36 + } 37 + static inline int ksft_exit_fail(void) 38 + { 39 + exit(1); 40 + } 41 + #endif 42 + 43 + #define NSEC_PER_SEC 1000000000LL 44 + 45 + #define KTIME_MAX ((long long)~((unsigned long long)1 << 63)) 46 + #define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) 47 + 48 + #define YEAR_1901 (-0x7fffffffL) 49 + #define YEAR_1970 1 50 + #define YEAR_2038 0x7fffffffL /*overflows 32bit time_t */ 51 + #define YEAR_2262 KTIME_SEC_MAX /*overflows 64bit ktime_t */ 52 + #define YEAR_MAX ((long long)((1ULL<<63)-1)) /*overflows 64bit time_t */ 53 + 54 + int is32bits(void) 55 + { 56 + return (sizeof(long) == 4); 57 + } 58 + 59 + int settime(long long time) 60 + { 61 + struct timeval now; 62 + int ret; 63 + 64 + now.tv_sec = (time_t)time; 65 + now.tv_usec = 0; 66 + 67 + ret = settimeofday(&now, NULL); 68 + 69 + printf("Setting time to 0x%lx: %d\n", (long)time, ret); 70 + return ret; 71 + } 72 + 73 + int do_tests(void) 74 + { 75 + int ret; 76 + 77 + ret = system("date"); 78 + ret = system("./inconsistency-check -c 0 -t 20"); 79 + ret |= system("./nanosleep"); 80 + ret |= system("./nsleep-lat"); 81 + return ret; 82 + 83 + } 84 + 85 + int main(int argc, char *argv[]) 86 + { 87 + int ret = 0; 88 + int opt, dangerous = 0; 89 + time_t start; 90 + 91 + /* Process arguments */ 92 + while ((opt = getopt(argc, argv, "d")) != -1) { 93 + switch (opt) { 94 + case 'd': 95 + dangerous = 1; 96 + } 97 + } 98 + 99 + start = time(0); 100 + 101 + /* First test that crazy values don't work */ 102 + if (!settime(YEAR_1901)) { 103 + ret = -1; 104 + goto out; 105 + } 106 + if (!settime(YEAR_MAX)) { 107 + ret = -1; 108 + goto out; 109 + } 110 + if (!is32bits() && !settime(YEAR_2262)) { 111 + ret = -1; 112 + goto out; 113 + } 114 + 115 + /* Now test behavior near edges */ 116 + settime(YEAR_1970); 117 + ret = do_tests(); 118 + if (ret) 119 + goto out; 120 + 121 + settime(YEAR_2038 - 600); 122 + ret = do_tests(); 123 + if (ret) 124 + goto out; 125 + 126 + /* The rest of the tests can blowup on 32bit systems */ 127 + if (is32bits() && !dangerous) 128 + goto out; 129 + /* Test rollover behavior 32bit edge */ 130 + settime(YEAR_2038 - 10); 131 + ret = do_tests(); 132 + if (ret) 133 + goto out; 134 + 135 + settime(YEAR_2262 - 600); 136 + ret = do_tests(); 137 + 138 + out: 139 + /* restore clock */ 140 + settime(start); 141 + if (ret) 142 + return ksft_exit_fail(); 143 + return ksft_exit_pass(); 144 + }