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 * clock_adjtime() syscall might have as execution path:
9 *
10 * 1) a regular POSIX clock (only REALTIME clock implements adjtime())
11 * - will behave exactly like adjtimex() system call.
12 * - only one being tested here.
13 *
14 * 2) a dynamic POSIX clock (which ops are implemented by PTP clocks)
15 * - will trigger the PTP clock driver function "adjtime()"
16 * - different implementations from one PTP clock to another
17 * - might return EOPNOTSUPP (like ptp_kvm_caps, for example)
18 * - no entry point for clock_adjtime(), missing "CLOCK_PTP" model
19 *
20 * so it is sane to check for the following errors:
21 *
22 * EINVAL - clock id being used does not exist
23 *
24 * EFAULT - (struct timex *) does not point to valid memory
25 *
26 * EINVAL - ADJ_OFFSET + .offset outside range -512000 < x < 512000
27 * (after 2.6.26, kernels normalize to the limit if outside range)
28 *
29 * EINVAL - ADJ_FREQUENCY + .freq outside range -32768000 < x < 3276800
30 * (after 2.6.26, kernels normalize to the limit if outside range)
31 *
32 * EINVAL - .tick outside permitted range (900000/HZ < .tick < 1100000/HZ)
33 *
34 * EPERM - .modes is neither 0 nor ADJ_OFFSET_SS_READ (CAP_SYS_TIME required)
35 *
36 * EINVAL - .status other than those listed bellow
37 *
38 * For ADJ_STATUS, consider the following flags:
39 *
40 * rw STA_PLL - enable phase-locked loop updates (ADJ_OFFSET)
41 * rw STA_PPSFREQ - enable PPS (pulse-per-second) freq discipline
42 * rw STA_PPSTIME - enable PPS time discipline
43 * rw STA_FLL - select freq-locked loop mode.
44 * rw STA_INS - ins leap sec after the last sec of UTC day (all days)
45 * rw STA_DEL - del leap sec at last sec of UTC day (all days)
46 * rw STA_UNSYNC - clock unsynced
47 * rw STA_FREQHOLD - hold freq. ADJ_OFFSET made w/out auto small adjs
48 * ro STA_PPSSIGNAL - valid PPS (pulse-per-second) signal is present
49 * ro STA_PPSJITTER - PPS signal jitter exceeded.
50 * ro STA_PPSWANDER - PPS signal wander exceeded.
51 * ro STA_PPSERROR - PPS signal calibration error.
52 * ro STA_CLOKERR - clock HW fault.
53 * ro STA_NANO - 0 = us, 1 = ns (set = ADJ_NANO, cl = ADJ_MICRO)
54 * rw STA_MODE - mode: 0 = phased locked loop. 1 = freq locked loop
55 * ro STA_CLK - clock source. unused.
56 */
57
58 #include "clock_adjtime.h"
59
60 static long hz;
61 static struct timex saved, ttxc;
62 static int supported;
63
64 static void cleanup(void);
65
66 struct test_case {
67 clockid_t clktype;
68 unsigned int modes;
69 long lowlimit;
70 long highlimit;
71 long *ptr;
72 long delta;
73 int exp_err;
74 int droproot;
75 };
76
77 struct test_case tc[] = {
78 {
79 .clktype = MAX_CLOCKS,
80 .exp_err = EINVAL,
81 },
82 {
83 .clktype = MAX_CLOCKS + 1,
84 .exp_err = EINVAL,
85 },
86 {
87 .clktype = CLOCK_REALTIME,
88 .modes = ADJ_ALL,
89 .exp_err = EFAULT,
90 },
91 {
92 .clktype = CLOCK_REALTIME,
93 .modes = ADJ_TICK,
94 .lowlimit = 900000,
95 .ptr = &ttxc.tick,
96 .delta = 1,
97 .exp_err = EINVAL,
98 },
99 {
100 .clktype = CLOCK_REALTIME,
101 .modes = ADJ_TICK,
102 .highlimit = 1100000,
103 .ptr = &ttxc.tick,
104 .delta = 1,
105 .exp_err = EINVAL,
106 },
107 {
108 .clktype = CLOCK_REALTIME,
109 .modes = ADJ_ALL,
110 .exp_err = EPERM,
111 .droproot = 1,
112 },
113 };
114
verify_clock_adjtime(unsigned int i)115 static void verify_clock_adjtime(unsigned int i)
116 {
117 uid_t whoami = 0;
118 struct timex *txcptr;
119 struct passwd *nobody;
120 static const char name[] = "nobody";
121
122 txcptr = &ttxc;
123
124 memset(txcptr, 0, sizeof(struct timex));
125
126 SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, txcptr);
127 timex_show("GET", *txcptr);
128
129 if (tc[i].droproot) {
130 nobody = SAFE_GETPWNAM(name);
131 whoami = nobody->pw_uid;
132 SAFE_SETEUID(whoami);
133 }
134
135 txcptr->modes = tc[i].modes;
136
137 if (tc[i].ptr) {
138
139 if (tc[i].lowlimit)
140 *tc[i].ptr = tc[i].lowlimit - tc[i].delta;
141
142 if (tc[i].highlimit)
143 *tc[i].ptr = tc[i].highlimit + tc[i].delta;
144 }
145
146 /* special case: EFAULT for bad addresses */
147 if (tc[i].exp_err == EFAULT)
148 txcptr = tst_get_bad_addr(cleanup);
149
150 TEST(sys_clock_adjtime(tc[i].clktype, txcptr));
151 if (txcptr && tc[i].exp_err != EFAULT)
152 timex_show("TEST", *txcptr);
153
154 if (TST_RET >= 0) {
155 tst_res(TFAIL, "clock_adjtime(): passed unexpectedly (mode=%x, "
156 "uid=%d)", tc[i].modes, whoami);
157 return;
158 }
159
160 if (tc[i].exp_err != TST_ERR) {
161 tst_res(TFAIL | TTERRNO, "clock_adjtime(): expected %d but "
162 "failed with %d (mode=%x, uid=%d)",
163 tc[i].exp_err, TST_ERR, tc[i].modes, whoami);
164 return;
165 }
166
167 tst_res(TPASS, "clock_adjtime(): failed as expected (mode=0x%x, "
168 "uid=%d)", tc[i].modes, whoami);
169
170 if (tc[i].droproot)
171 SAFE_SETEUID(0);
172 }
173
setup(void)174 static void setup(void)
175 {
176 size_t i;
177 int rval;
178
179 rval = SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &saved);
180 supported = 1;
181
182 if (rval != TIME_OK && rval != TIME_ERROR) {
183 timex_show("SAVE_STATUS", saved);
184 tst_brk(TBROK | TTERRNO, "clock has on-going leap changes, "
185 "returned: %i", rval);
186 }
187
188 hz = SAFE_SYSCONF(_SC_CLK_TCK);
189
190 /* fix high and low limits by dividing it per HZ value */
191
192 for (i = 0; i < ARRAY_SIZE(tc); i++) {
193 if (tc[i].modes == ADJ_TICK) {
194 tc[i].highlimit /= hz;
195 tc[i].lowlimit /= hz;
196 }
197 }
198 }
199
cleanup(void)200 static void cleanup(void)
201 {
202 if (supported == 0)
203 return;
204
205 saved.modes = ADJ_ALL;
206
207 /* restore clock resolution based on original status flag */
208
209 if (saved.status & STA_NANO)
210 saved.modes |= ADJ_NANO;
211 else
212 saved.modes |= ADJ_MICRO;
213
214 /* restore original clock flags */
215
216 SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &saved);
217 }
218
219 static struct tst_test test = {
220 .test = verify_clock_adjtime,
221 .setup = setup,
222 .cleanup = cleanup,
223 .tcnt = ARRAY_SIZE(tc),
224 .needs_root = 1,
225 .restore_wallclock = 1,
226 };
227