• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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