1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2019 Linaro Limited. All rights reserved.
4 * Author: Rafael David Tinoco <rafael.tinoco@linaro.org>
5 */
6
7 /*
8 * Basic tests for errors of clock_settime(2) on different clock types.
9 */
10
11 #include "config.h"
12 #include "tst_test.h"
13 #include "lapi/syscalls.h"
14 #include "tst_timer.h"
15 #include "tst_safe_clocks.h"
16
17 #define DELTA_SEC 10
18 #define NSEC_PER_SEC (1000000000L)
19
20 struct test_case {
21 clockid_t type;
22 struct timespec newtime;
23 int exp_err;
24 int replace;
25 };
26
27 struct test_case tc[] = {
28 { /* case 01: REALTIME: timespec NULL */
29 .type = CLOCK_REALTIME,
30 .exp_err = EFAULT,
31 .replace = 1,
32 },
33 { /* case 02: REALTIME: tv_sec = -1 */
34 .type = CLOCK_REALTIME,
35 .newtime.tv_sec = -1,
36 .exp_err = EINVAL,
37 .replace = 1,
38 },
39 { /* case 03: REALTIME: tv_nsec = -1 */
40 .type = CLOCK_REALTIME,
41 .newtime.tv_nsec = -1,
42 .exp_err = EINVAL,
43 .replace = 1,
44 },
45 { /* case 04: REALTIME: tv_nsec = 1s+1 */
46 .type = CLOCK_REALTIME,
47 .newtime.tv_nsec = NSEC_PER_SEC + 1,
48 .exp_err = EINVAL,
49 .replace = 1,
50 },
51 { /* case 05: MONOTONIC */
52 .type = CLOCK_MONOTONIC,
53 .exp_err = EINVAL,
54 },
55 { /* case 06: MAXCLOCK */
56 .type = MAX_CLOCKS,
57 .exp_err = EINVAL,
58 },
59 { /* case 07: MAXCLOCK+1 */
60 .type = MAX_CLOCKS + 1,
61 .exp_err = EINVAL,
62 },
63 /* Linux specific */
64 { /* case 08: CLOCK_MONOTONIC_COARSE */
65 .type = CLOCK_MONOTONIC_COARSE,
66 .exp_err = EINVAL,
67 },
68 { /* case 09: CLOCK_MONOTONIC_RAW */
69 .type = CLOCK_MONOTONIC_RAW,
70 .exp_err = EINVAL,
71 },
72 { /* case 10: CLOCK_BOOTTIME */
73 .type = CLOCK_BOOTTIME,
74 .exp_err = EINVAL,
75 },
76 { /* case 11: CLOCK_PROCESS_CPUTIME_ID */
77 .type = CLOCK_PROCESS_CPUTIME_ID,
78 .exp_err = EINVAL,
79 },
80 { /* case 12: CLOCK_THREAD_CPUTIME_ID */
81 .type = CLOCK_THREAD_CPUTIME_ID,
82 .exp_err = EINVAL,
83 },
84 };
85
86 /*
87 * Some tests may cause libc to segfault when passing bad arguments.
88 */
sys_clock_settime(clockid_t clk_id,struct timespec * tp)89 static int sys_clock_settime(clockid_t clk_id, struct timespec *tp)
90 {
91 return tst_syscall(__NR_clock_settime, clk_id, tp);
92 }
93
verify_clock_settime(unsigned int i)94 static void verify_clock_settime(unsigned int i)
95 {
96 struct timespec spec, *specptr;
97
98 specptr = &spec;
99
100 if (tc[i].replace == 0) {
101
102 SAFE_CLOCK_GETTIME(CLOCK_REALTIME, specptr);
103
104 /* add 1 sec to wall clock */
105 specptr->tv_sec += 1;
106
107 } else {
108
109 /* use given time spec */
110 *specptr = tc[i].newtime;
111 }
112
113 /* bad pointer case */
114 if (tc[i].exp_err == EFAULT)
115 specptr = tst_get_bad_addr(NULL);
116
117 TEST(sys_clock_settime(tc[i].type, specptr));
118
119 if (TST_RET == -1) {
120
121 if (tc[i].exp_err == TST_ERR) {
122 tst_res(TPASS | TTERRNO,
123 "clock_settime(%s): failed as expected",
124 tst_clock_name(tc[i].type));
125 return;
126 }
127
128 tst_res(TFAIL | TTERRNO, "clock_settime(2): clock %s "
129 "expected to fail with %s",
130 tst_clock_name(tc[i].type),
131 tst_strerrno(tc[i].exp_err));
132
133 return;
134 }
135
136 tst_res(TFAIL | TTERRNO, "clock_settime(2): clock %s passed "
137 "unexpectedly, expected %s",
138 tst_clock_name(tc[i].type),
139 tst_strerrno(tc[i].exp_err));
140 }
141
142 static struct tst_test test = {
143 .test = verify_clock_settime,
144 .tcnt = ARRAY_SIZE(tc),
145 .needs_root = 1,
146 .restore_wallclock = 1,
147 };
148