1 // SPDX-License-Identifier: GPL-2.0
2 
3 #define _GNU_SOURCE
4 
5 #include <elf.h>
6 #include <pthread.h>
7 #include <stdbool.h>
8 
9 #include <asm/prctl.h>
10 #include <sys/ptrace.h>
11 #include <sys/syscall.h>
12 #include <sys/uio.h>
13 #include <sys/wait.h>
14 
15 #include "helpers.h"
16 #include "xstate.h"
17 
18 /*
19  * The userspace xstate test suite is designed to be generic and operates
20  * with randomized xstate data. However, some states require special handling:
21  *
22  * - PKRU and XTILECFG need specific adjustments, such as modifying
23  *   randomization behavior or using fixed values.
24  * - But, PKRU already has a dedicated test suite in /tools/selftests/mm.
25  * - Legacy states (FP and SSE) are excluded, as they are not considered
26  *   part of extended states (xstates) and their usage is already deeply
27  *   integrated into user-space libraries.
28  */
29 #define XFEATURE_MASK_TEST_SUPPORTED	\
30 	((1 << XFEATURE_YMM) |		\
31 	 (1 << XFEATURE_OPMASK)	|	\
32 	 (1 << XFEATURE_ZMM_Hi256) |	\
33 	 (1 << XFEATURE_Hi16_ZMM) |	\
34 	 (1 << XFEATURE_XTILEDATA))
35 
xgetbv(uint32_t index)36 static inline uint64_t xgetbv(uint32_t index)
37 {
38 	uint32_t eax, edx;
39 
40 	asm volatile("xgetbv" : "=a" (eax), "=d" (edx) : "c" (index));
41 	return eax + ((uint64_t)edx << 32);
42 }
43 
get_xstatebv(struct xsave_buffer * xbuf)44 static inline uint64_t get_xstatebv(struct xsave_buffer *xbuf)
45 {
46 	return *(uint64_t *)(&xbuf->header);
47 }
48 
49 static struct xstate_info xstate;
50 
51 struct futex_info {
52 	unsigned int iterations;
53 	struct futex_info *next;
54 	pthread_mutex_t mutex;
55 	pthread_t thread;
56 	bool valid;
57 	int nr;
58 };
59 
load_rand_xstate(struct xstate_info * xstate,struct xsave_buffer * xbuf)60 static inline void load_rand_xstate(struct xstate_info *xstate, struct xsave_buffer *xbuf)
61 {
62 	clear_xstate_header(xbuf);
63 	set_xstatebv(xbuf, xstate->mask);
64 	set_rand_data(xstate, xbuf);
65 	xrstor(xbuf, xstate->mask);
66 }
67 
load_init_xstate(struct xstate_info * xstate,struct xsave_buffer * xbuf)68 static inline void load_init_xstate(struct xstate_info *xstate, struct xsave_buffer *xbuf)
69 {
70 	clear_xstate_header(xbuf);
71 	xrstor(xbuf, xstate->mask);
72 }
73 
copy_xstate(struct xsave_buffer * xbuf_dst,struct xsave_buffer * xbuf_src)74 static inline void copy_xstate(struct xsave_buffer *xbuf_dst, struct xsave_buffer *xbuf_src)
75 {
76 	memcpy(&xbuf_dst->bytes[xstate.xbuf_offset],
77 	       &xbuf_src->bytes[xstate.xbuf_offset],
78 	       xstate.size);
79 }
80 
validate_xstate_same(struct xsave_buffer * xbuf1,struct xsave_buffer * xbuf2)81 static inline bool validate_xstate_same(struct xsave_buffer *xbuf1, struct xsave_buffer *xbuf2)
82 {
83 	int ret;
84 
85 	ret = memcmp(&xbuf1->bytes[xstate.xbuf_offset],
86 		     &xbuf2->bytes[xstate.xbuf_offset],
87 		     xstate.size);
88 	return ret == 0;
89 }
90 
validate_xregs_same(struct xsave_buffer * xbuf1)91 static inline bool validate_xregs_same(struct xsave_buffer *xbuf1)
92 {
93 	struct xsave_buffer *xbuf2;
94 	bool ret;
95 
96 	xbuf2 = alloc_xbuf();
97 	if (!xbuf2)
98 		ksft_exit_fail_msg("failed to allocate XSAVE buffer\n");
99 
100 	xsave(xbuf2, xstate.mask);
101 	ret = validate_xstate_same(xbuf1, xbuf2);
102 
103 	free(xbuf2);
104 	return ret;
105 }
106 
107 /* Context switching test */
108 
check_xstate(void * info)109 static void *check_xstate(void *info)
110 {
111 	struct futex_info *finfo = (struct futex_info *)info;
112 	struct xsave_buffer *xbuf;
113 	int i;
114 
115 	xbuf = alloc_xbuf();
116 	if (!xbuf)
117 		ksft_exit_fail_msg("unable to allocate XSAVE buffer\n");
118 
119 	/*
120 	 * Load random data into 'xbuf' and then restore it to the xstate
121 	 * registers.
122 	 */
123 	load_rand_xstate(&xstate, xbuf);
124 	finfo->valid = true;
125 
126 	for (i = 0; i < finfo->iterations; i++) {
127 		pthread_mutex_lock(&finfo->mutex);
128 
129 		/*
130 		 * Ensure the register values have not diverged from the
131 		 * record. Then reload a new random value.  If it failed
132 		 * ever before, skip it.
133 		 */
134 		if (finfo->valid) {
135 			finfo->valid = validate_xregs_same(xbuf);
136 			load_rand_xstate(&xstate, xbuf);
137 		}
138 
139 		/*
140 		 * The last thread's last unlock will be for thread 0's
141 		 * mutex. However, thread 0 will have already exited the
142 		 * loop and the mutex will already be unlocked.
143 		 *
144 		 * Because this is not an ERRORCHECK mutex, that
145 		 * inconsistency will be silently ignored.
146 		 */
147 		pthread_mutex_unlock(&finfo->next->mutex);
148 	}
149 
150 	free(xbuf);
151 	return finfo;
152 }
153 
create_threads(uint32_t num_threads,uint32_t iterations,struct futex_info * finfo)154 static void create_threads(uint32_t num_threads, uint32_t iterations, struct futex_info *finfo)
155 {
156 	int i;
157 
158 	for (i = 0; i < num_threads; i++) {
159 		int next_nr;
160 
161 		finfo[i].nr = i;
162 		finfo[i].iterations = iterations;
163 
164 		/*
165 		 * Thread 'i' will wait on this mutex to be unlocked.
166 		 * Lock it immediately after initialization:
167 		 */
168 		pthread_mutex_init(&finfo[i].mutex, NULL);
169 		pthread_mutex_lock(&finfo[i].mutex);
170 
171 		next_nr = (i + 1) % num_threads;
172 		finfo[i].next = &finfo[next_nr];
173 
174 		if (pthread_create(&finfo[i].thread, NULL, check_xstate, &finfo[i]))
175 			ksft_exit_fail_msg("pthread_create() failed\n");
176 	}
177 }
178 
checkout_threads(uint32_t num_threads,struct futex_info * finfo)179 static bool checkout_threads(uint32_t num_threads, struct futex_info *finfo)
180 {
181 	void *thread_retval;
182 	bool valid = true;
183 	int err, i;
184 
185 	for (i = 0; i < num_threads; i++) {
186 		err = pthread_join(finfo[i].thread, &thread_retval);
187 		if (err)
188 			ksft_exit_fail_msg("pthread_join() failed for thread %d err: %d\n", i, err);
189 
190 		if (thread_retval != &finfo[i]) {
191 			ksft_exit_fail_msg("unexpected thread retval for thread %d: %p\n",
192 					   i, thread_retval);
193 		}
194 
195 		valid &= finfo[i].valid;
196 	}
197 
198 	return valid;
199 }
200 
affinitize_cpu0(void)201 static void affinitize_cpu0(void)
202 {
203 	cpu_set_t cpuset;
204 
205 	CPU_ZERO(&cpuset);
206 	CPU_SET(0, &cpuset);
207 
208 	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
209 		ksft_exit_fail_msg("sched_setaffinity to CPU 0 failed\n");
210 }
211 
test_context_switch(uint32_t num_threads,uint32_t iterations)212 static void test_context_switch(uint32_t num_threads, uint32_t iterations)
213 {
214 	struct futex_info *finfo;
215 
216 	/* Affinitize to one CPU to force context switches */
217 	affinitize_cpu0();
218 
219 	printf("[RUN]\t%s: check context switches, %d iterations, %d threads.\n",
220 	       xstate.name, iterations, num_threads);
221 
222 	finfo = malloc(sizeof(*finfo) * num_threads);
223 	if (!finfo)
224 		ksft_exit_fail_msg("unable allocate memory\n");
225 
226 	create_threads(num_threads, iterations, finfo);
227 
228 	/*
229 	 * This thread wakes up thread 0
230 	 * Thread 0 will wake up 1
231 	 * Thread 1 will wake up 2
232 	 * ...
233 	 * The last thread will wake up 0
234 	 *
235 	 * This will repeat for the configured
236 	 * number of iterations.
237 	 */
238 	pthread_mutex_unlock(&finfo[0].mutex);
239 
240 	/* Wait for all the threads to finish: */
241 	if (checkout_threads(num_threads, finfo))
242 		printf("[OK]\tNo incorrect case was found.\n");
243 	else
244 		printf("[FAIL]\tFailed with context switching test.\n");
245 
246 	free(finfo);
247 }
248 
249 /*
250  * Ptrace test for the ABI format as described in arch/x86/include/asm/user.h
251  */
252 
253 /*
254  * Make sure the ptracee has the expanded kernel buffer on the first use.
255  * Then, initialize the state before performing the state injection from
256  * the ptracer. For non-dynamic states, this is benign.
257  */
ptracee_touch_xstate(void)258 static inline void ptracee_touch_xstate(void)
259 {
260 	struct xsave_buffer *xbuf;
261 
262 	xbuf = alloc_xbuf();
263 
264 	load_rand_xstate(&xstate, xbuf);
265 	load_init_xstate(&xstate, xbuf);
266 
267 	free(xbuf);
268 }
269 
270 /*
271  * Ptracer injects the randomized xstate data. It also reads before and
272  * after that, which will execute the kernel's state copy functions.
273  */
ptracer_inject_xstate(pid_t target)274 static void ptracer_inject_xstate(pid_t target)
275 {
276 	uint32_t xbuf_size = get_xbuf_size();
277 	struct xsave_buffer *xbuf1, *xbuf2;
278 	struct iovec iov;
279 
280 	/*
281 	 * Allocate buffers to keep data while ptracer can write the
282 	 * other buffer
283 	 */
284 	xbuf1 = alloc_xbuf();
285 	xbuf2 = alloc_xbuf();
286 	if (!xbuf1 || !xbuf2)
287 		ksft_exit_fail_msg("unable to allocate XSAVE buffer\n");
288 
289 	iov.iov_base = xbuf1;
290 	iov.iov_len  = xbuf_size;
291 
292 	if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
293 		ksft_exit_fail_msg("PTRACE_GETREGSET failed\n");
294 
295 	printf("[RUN]\t%s: inject xstate via ptrace().\n", xstate.name);
296 
297 	load_rand_xstate(&xstate, xbuf1);
298 	copy_xstate(xbuf2, xbuf1);
299 
300 	if (ptrace(PTRACE_SETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
301 		ksft_exit_fail_msg("PTRACE_SETREGSET failed\n");
302 
303 	if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
304 		ksft_exit_fail_msg("PTRACE_GETREGSET failed\n");
305 
306 	if (*(uint64_t *)get_fpx_sw_bytes(xbuf1) == xgetbv(0))
307 		printf("[OK]\t'xfeatures' in SW reserved area was correctly written\n");
308 	else
309 		printf("[FAIL]\t'xfeatures' in SW reserved area was not correctly written\n");
310 
311 	if (validate_xstate_same(xbuf2, xbuf1))
312 		printf("[OK]\txstate was correctly updated.\n");
313 	else
314 		printf("[FAIL]\txstate was not correctly updated.\n");
315 
316 	free(xbuf1);
317 	free(xbuf2);
318 }
319 
test_ptrace(void)320 static void test_ptrace(void)
321 {
322 	pid_t child;
323 	int status;
324 
325 	child = fork();
326 	if (child < 0) {
327 		ksft_exit_fail_msg("fork() failed\n");
328 	} else if (!child) {
329 		if (ptrace(PTRACE_TRACEME, 0, NULL, NULL))
330 			ksft_exit_fail_msg("PTRACE_TRACEME failed\n");
331 
332 		ptracee_touch_xstate();
333 
334 		raise(SIGTRAP);
335 		_exit(0);
336 	}
337 
338 	do {
339 		wait(&status);
340 	} while (WSTOPSIG(status) != SIGTRAP);
341 
342 	ptracer_inject_xstate(child);
343 
344 	ptrace(PTRACE_DETACH, child, NULL, NULL);
345 	wait(&status);
346 	if (!WIFEXITED(status) || WEXITSTATUS(status))
347 		ksft_exit_fail_msg("ptracee exit error\n");
348 }
349 
350 /*
351  * Test signal delivery for the ABI compatibility.
352  * See the ABI format: arch/x86/include/uapi/asm/sigcontext.h
353  */
354 
355 /*
356  * Avoid using printf() in signal handlers as it is not
357  * async-signal-safe.
358  */
359 #define SIGNAL_BUF_LEN 1000
360 static char signal_message_buffer[SIGNAL_BUF_LEN];
sig_print(char * msg)361 static void sig_print(char *msg)
362 {
363 	int left = SIGNAL_BUF_LEN - strlen(signal_message_buffer) - 1;
364 
365 	strncat(signal_message_buffer, msg, left);
366 }
367 
368 static struct xsave_buffer *stashed_xbuf;
369 
validate_sigfpstate(int sig,siginfo_t * si,void * ctx_void)370 static void validate_sigfpstate(int sig, siginfo_t *si, void *ctx_void)
371 {
372 	ucontext_t *ctx = (ucontext_t *)ctx_void;
373 	void *xbuf = ctx->uc_mcontext.fpregs;
374 	struct _fpx_sw_bytes *sw_bytes;
375 	uint32_t magic2;
376 
377 	/* Reset the signal message buffer: */
378 	signal_message_buffer[0] = '\0';
379 
380 	sw_bytes = get_fpx_sw_bytes(xbuf);
381 	if (sw_bytes->magic1 == FP_XSTATE_MAGIC1)
382 		sig_print("[OK]\t'magic1' is valid\n");
383 	else
384 		sig_print("[FAIL]\t'magic1' is not valid\n");
385 
386 	if (get_fpx_sw_bytes_features(xbuf) & xstate.mask)
387 		sig_print("[OK]\t'xfeatures' in SW reserved area is valid\n");
388 	else
389 		sig_print("[FAIL]\t'xfeatures' in SW reserved area is not valid\n");
390 
391 	if (get_xstatebv(xbuf) & xstate.mask)
392 		sig_print("[OK]\t'xfeatures' in XSAVE header is valid\n");
393 	else
394 		sig_print("[FAIL]\t'xfeatures' in XSAVE header is not valid\n");
395 
396 	if (validate_xstate_same(stashed_xbuf, xbuf))
397 		sig_print("[OK]\txstate delivery was successful\n");
398 	else
399 		sig_print("[FAIL]\txstate delivery was not successful\n");
400 
401 	magic2 = *(uint32_t *)(xbuf + sw_bytes->xstate_size);
402 	if (magic2 == FP_XSTATE_MAGIC2)
403 		sig_print("[OK]\t'magic2' is valid\n");
404 	else
405 		sig_print("[FAIL]\t'magic2' is not valid\n");
406 
407 	set_rand_data(&xstate, xbuf);
408 	copy_xstate(stashed_xbuf, xbuf);
409 }
410 
test_signal(void)411 static void test_signal(void)
412 {
413 	bool valid_xstate;
414 
415 	/*
416 	 * The signal handler will access this to verify xstate context
417 	 * preservation.
418 	 */
419 	stashed_xbuf = alloc_xbuf();
420 	if (!stashed_xbuf)
421 		ksft_exit_fail_msg("unable to allocate XSAVE buffer\n");
422 
423 	printf("[RUN]\t%s: load xstate and raise SIGUSR1\n", xstate.name);
424 
425 	sethandler(SIGUSR1, validate_sigfpstate, 0);
426 
427 	load_rand_xstate(&xstate, stashed_xbuf);
428 
429 	raise(SIGUSR1);
430 
431 	/*
432 	 * Immediately record the test result, deferring printf() to
433 	 * prevent unintended state contamination by that.
434 	 */
435 	valid_xstate = validate_xregs_same(stashed_xbuf);
436 	printf("%s", signal_message_buffer);
437 
438 	printf("[RUN]\t%s: load new xstate from sighandler and check it after sigreturn\n",
439 	       xstate.name);
440 
441 	if (valid_xstate)
442 		printf("[OK]\txstate was restored correctly\n");
443 	else
444 		printf("[FAIL]\txstate restoration failed\n");
445 
446 	clearhandler(SIGUSR1);
447 	free(stashed_xbuf);
448 }
449 
test_xstate(uint32_t feature_num)450 void test_xstate(uint32_t feature_num)
451 {
452 	const unsigned int ctxtsw_num_threads = 5, ctxtsw_iterations = 10;
453 	unsigned long features;
454 	long rc;
455 
456 	if (!(XFEATURE_MASK_TEST_SUPPORTED & (1 << feature_num))) {
457 		ksft_print_msg("The xstate test does not fully support the component %u, yet.\n",
458 			       feature_num);
459 		return;
460 	}
461 
462 	rc = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_SUPP, &features);
463 	if (rc || !(features & (1 << feature_num))) {
464 		ksft_print_msg("The kernel does not support feature number: %u\n", feature_num);
465 		return;
466 	}
467 
468 	xstate = get_xstate_info(feature_num);
469 	if (!xstate.size || !xstate.xbuf_offset) {
470 		ksft_exit_fail_msg("invalid state size/offset (%d/%d)\n",
471 				   xstate.size, xstate.xbuf_offset);
472 	}
473 
474 	test_context_switch(ctxtsw_num_threads, ctxtsw_iterations);
475 	test_ptrace();
476 	test_signal();
477 }
478