xref: /linux/tools/testing/selftests/x86/ldt_gdt.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
1 /*
2  * ldt_gdt.c - Test cases for LDT and GDT access
3  * Copyright (c) 2015 Andrew Lutomirski
4  */
5 
6 #define _GNU_SOURCE
7 #include <err.h>
8 #include <stdio.h>
9 #include <stdint.h>
10 #include <signal.h>
11 #include <setjmp.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <unistd.h>
16 #include <sys/syscall.h>
17 #include <asm/ldt.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <stdbool.h>
21 #include <pthread.h>
22 #include <sched.h>
23 #include <linux/futex.h>
24 
25 #define AR_ACCESSED		(1<<8)
26 
27 #define AR_TYPE_RODATA		(0 * (1<<9))
28 #define AR_TYPE_RWDATA		(1 * (1<<9))
29 #define AR_TYPE_RODATA_EXPDOWN	(2 * (1<<9))
30 #define AR_TYPE_RWDATA_EXPDOWN	(3 * (1<<9))
31 #define AR_TYPE_XOCODE		(4 * (1<<9))
32 #define AR_TYPE_XRCODE		(5 * (1<<9))
33 #define AR_TYPE_XOCODE_CONF	(6 * (1<<9))
34 #define AR_TYPE_XRCODE_CONF	(7 * (1<<9))
35 
36 #define AR_DPL3			(3 * (1<<13))
37 
38 #define AR_S			(1 << 12)
39 #define AR_P			(1 << 15)
40 #define AR_AVL			(1 << 20)
41 #define AR_L			(1 << 21)
42 #define AR_DB			(1 << 22)
43 #define AR_G			(1 << 23)
44 
45 static int nerrs;
46 
47 static void check_invalid_segment(uint16_t index, int ldt)
48 {
49 	uint32_t has_limit = 0, has_ar = 0, limit, ar;
50 	uint32_t selector = (index << 3) | (ldt << 2) | 3;
51 
52 	asm ("lsl %[selector], %[limit]\n\t"
53 	     "jnz 1f\n\t"
54 	     "movl $1, %[has_limit]\n\t"
55 	     "1:"
56 	     : [limit] "=r" (limit), [has_limit] "+rm" (has_limit)
57 	     : [selector] "r" (selector));
58 	asm ("larl %[selector], %[ar]\n\t"
59 	     "jnz 1f\n\t"
60 	     "movl $1, %[has_ar]\n\t"
61 	     "1:"
62 	     : [ar] "=r" (ar), [has_ar] "+rm" (has_ar)
63 	     : [selector] "r" (selector));
64 
65 	if (has_limit || has_ar) {
66 		printf("[FAIL]\t%s entry %hu is valid but should be invalid\n",
67 		       (ldt ? "LDT" : "GDT"), index);
68 		nerrs++;
69 	} else {
70 		printf("[OK]\t%s entry %hu is invalid\n",
71 		       (ldt ? "LDT" : "GDT"), index);
72 	}
73 }
74 
75 static void check_valid_segment(uint16_t index, int ldt,
76 				uint32_t expected_ar, uint32_t expected_limit,
77 				bool verbose)
78 {
79 	uint32_t has_limit = 0, has_ar = 0, limit, ar;
80 	uint32_t selector = (index << 3) | (ldt << 2) | 3;
81 
82 	asm ("lsl %[selector], %[limit]\n\t"
83 	     "jnz 1f\n\t"
84 	     "movl $1, %[has_limit]\n\t"
85 	     "1:"
86 	     : [limit] "=r" (limit), [has_limit] "+rm" (has_limit)
87 	     : [selector] "r" (selector));
88 	asm ("larl %[selector], %[ar]\n\t"
89 	     "jnz 1f\n\t"
90 	     "movl $1, %[has_ar]\n\t"
91 	     "1:"
92 	     : [ar] "=r" (ar), [has_ar] "+rm" (has_ar)
93 	     : [selector] "r" (selector));
94 
95 	if (!has_limit || !has_ar) {
96 		printf("[FAIL]\t%s entry %hu is invalid but should be valid\n",
97 		       (ldt ? "LDT" : "GDT"), index);
98 		nerrs++;
99 		return;
100 	}
101 
102 	if (ar != expected_ar) {
103 		printf("[FAIL]\t%s entry %hu has AR 0x%08X but expected 0x%08X\n",
104 		       (ldt ? "LDT" : "GDT"), index, ar, expected_ar);
105 		nerrs++;
106 	} else if (limit != expected_limit) {
107 		printf("[FAIL]\t%s entry %hu has limit 0x%08X but expected 0x%08X\n",
108 		       (ldt ? "LDT" : "GDT"), index, limit, expected_limit);
109 		nerrs++;
110 	} else if (verbose) {
111 		printf("[OK]\t%s entry %hu has AR 0x%08X and limit 0x%08X\n",
112 		       (ldt ? "LDT" : "GDT"), index, ar, limit);
113 	}
114 }
115 
116 static bool install_valid_mode(const struct user_desc *desc, uint32_t ar,
117 			       bool oldmode)
118 {
119 	int ret = syscall(SYS_modify_ldt, oldmode ? 1 : 0x11,
120 			  desc, sizeof(*desc));
121 	if (ret < -1)
122 		errno = -ret;
123 	if (ret == 0) {
124 		uint32_t limit = desc->limit;
125 		if (desc->limit_in_pages)
126 			limit = (limit << 12) + 4095;
127 		check_valid_segment(desc->entry_number, 1, ar, limit, true);
128 		return true;
129 	} else if (errno == ENOSYS) {
130 		printf("[OK]\tmodify_ldt returned -ENOSYS\n");
131 		return false;
132 	} else {
133 		if (desc->seg_32bit) {
134 			printf("[FAIL]\tUnexpected modify_ldt failure %d\n",
135 			       errno);
136 			nerrs++;
137 			return false;
138 		} else {
139 			printf("[OK]\tmodify_ldt rejected 16 bit segment\n");
140 			return false;
141 		}
142 	}
143 }
144 
145 static bool install_valid(const struct user_desc *desc, uint32_t ar)
146 {
147 	return install_valid_mode(desc, ar, false);
148 }
149 
150 static void install_invalid(const struct user_desc *desc, bool oldmode)
151 {
152 	int ret = syscall(SYS_modify_ldt, oldmode ? 1 : 0x11,
153 			  desc, sizeof(*desc));
154 	if (ret < -1)
155 		errno = -ret;
156 	if (ret == 0) {
157 		check_invalid_segment(desc->entry_number, 1);
158 	} else if (errno == ENOSYS) {
159 		printf("[OK]\tmodify_ldt returned -ENOSYS\n");
160 	} else {
161 		if (desc->seg_32bit) {
162 			printf("[FAIL]\tUnexpected modify_ldt failure %d\n",
163 			       errno);
164 			nerrs++;
165 		} else {
166 			printf("[OK]\tmodify_ldt rejected 16 bit segment\n");
167 		}
168 	}
169 }
170 
171 static int safe_modify_ldt(int func, struct user_desc *ptr,
172 			   unsigned long bytecount)
173 {
174 	int ret = syscall(SYS_modify_ldt, 0x11, ptr, bytecount);
175 	if (ret < -1)
176 		errno = -ret;
177 	return ret;
178 }
179 
180 static void fail_install(struct user_desc *desc)
181 {
182 	if (safe_modify_ldt(0x11, desc, sizeof(*desc)) == 0) {
183 		printf("[FAIL]\tmodify_ldt accepted a bad descriptor\n");
184 		nerrs++;
185 	} else if (errno == ENOSYS) {
186 		printf("[OK]\tmodify_ldt returned -ENOSYS\n");
187 	} else {
188 		printf("[OK]\tmodify_ldt failure %d\n", errno);
189 	}
190 }
191 
192 static void do_simple_tests(void)
193 {
194 	struct user_desc desc = {
195 		.entry_number    = 0,
196 		.base_addr       = 0,
197 		.limit           = 10,
198 		.seg_32bit       = 1,
199 		.contents        = 2, /* Code, not conforming */
200 		.read_exec_only  = 0,
201 		.limit_in_pages  = 0,
202 		.seg_not_present = 0,
203 		.useable         = 0
204 	};
205 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE | AR_S | AR_P | AR_DB);
206 
207 	desc.limit_in_pages = 1;
208 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE |
209 		      AR_S | AR_P | AR_DB | AR_G);
210 
211 	check_invalid_segment(1, 1);
212 
213 	desc.entry_number = 2;
214 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE |
215 		      AR_S | AR_P | AR_DB | AR_G);
216 
217 	check_invalid_segment(1, 1);
218 
219 	desc.base_addr = 0xf0000000;
220 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE |
221 		      AR_S | AR_P | AR_DB | AR_G);
222 
223 	desc.useable = 1;
224 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE |
225 		      AR_S | AR_P | AR_DB | AR_G | AR_AVL);
226 
227 	desc.seg_not_present = 1;
228 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE |
229 		      AR_S | AR_DB | AR_G | AR_AVL);
230 
231 	desc.seg_32bit = 0;
232 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE |
233 		      AR_S | AR_G | AR_AVL);
234 
235 	desc.seg_32bit = 1;
236 	desc.contents = 0;
237 	install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA |
238 		      AR_S | AR_DB | AR_G | AR_AVL);
239 
240 	desc.read_exec_only = 1;
241 	install_valid(&desc, AR_DPL3 | AR_TYPE_RODATA |
242 		      AR_S | AR_DB | AR_G | AR_AVL);
243 
244 	desc.contents = 1;
245 	install_valid(&desc, AR_DPL3 | AR_TYPE_RODATA_EXPDOWN |
246 		      AR_S | AR_DB | AR_G | AR_AVL);
247 
248 	desc.read_exec_only = 0;
249 	desc.limit_in_pages = 0;
250 	install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA_EXPDOWN |
251 		      AR_S | AR_DB | AR_AVL);
252 
253 	desc.contents = 3;
254 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE_CONF |
255 		      AR_S | AR_DB | AR_AVL);
256 
257 	desc.read_exec_only = 1;
258 	install_valid(&desc, AR_DPL3 | AR_TYPE_XOCODE_CONF |
259 		      AR_S | AR_DB | AR_AVL);
260 
261 	desc.read_exec_only = 0;
262 	desc.contents = 2;
263 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE |
264 		      AR_S | AR_DB | AR_AVL);
265 
266 	desc.read_exec_only = 1;
267 
268 #ifdef __x86_64__
269 	desc.lm = 1;
270 	install_valid(&desc, AR_DPL3 | AR_TYPE_XOCODE |
271 		      AR_S | AR_DB | AR_AVL);
272 	desc.lm = 0;
273 #endif
274 
275 	bool entry1_okay = install_valid(&desc, AR_DPL3 | AR_TYPE_XOCODE |
276 					 AR_S | AR_DB | AR_AVL);
277 
278 	if (entry1_okay) {
279 		printf("[RUN]\tTest fork\n");
280 		pid_t child = fork();
281 		if (child == 0) {
282 			nerrs = 0;
283 			check_valid_segment(desc.entry_number, 1,
284 					    AR_DPL3 | AR_TYPE_XOCODE |
285 					    AR_S | AR_DB | AR_AVL, desc.limit,
286 					    true);
287 			check_invalid_segment(1, 1);
288 			exit(nerrs ? 1 : 0);
289 		} else {
290 			int status;
291 			if (waitpid(child, &status, 0) != child ||
292 			    !WIFEXITED(status)) {
293 				printf("[FAIL]\tChild died\n");
294 				nerrs++;
295 			} else if (WEXITSTATUS(status) != 0) {
296 				printf("[FAIL]\tChild failed\n");
297 				nerrs++;
298 			} else {
299 				printf("[OK]\tChild succeeded\n");
300 			}
301 		}
302 
303 		printf("[RUN]\tTest size\n");
304 		int i;
305 		for (i = 0; i < 8192; i++) {
306 			desc.entry_number = i;
307 			desc.limit = i;
308 			if (safe_modify_ldt(0x11, &desc, sizeof(desc)) != 0) {
309 				printf("[FAIL]\tFailed to install entry %d\n", i);
310 				nerrs++;
311 				break;
312 			}
313 		}
314 		for (int j = 0; j < i; j++) {
315 			check_valid_segment(j, 1, AR_DPL3 | AR_TYPE_XOCODE |
316 					    AR_S | AR_DB | AR_AVL, j, false);
317 		}
318 		printf("[DONE]\tSize test\n");
319 	} else {
320 		printf("[SKIP]\tSkipping fork and size tests because we have no LDT\n");
321 	}
322 
323 	/* Test entry_number too high. */
324 	desc.entry_number = 8192;
325 	fail_install(&desc);
326 
327 	/* Test deletion and actions mistakeable for deletion. */
328 	memset(&desc, 0, sizeof(desc));
329 	install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA | AR_S | AR_P);
330 
331 	desc.seg_not_present = 1;
332 	install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA | AR_S);
333 
334 	desc.seg_not_present = 0;
335 	desc.read_exec_only = 1;
336 	install_valid(&desc, AR_DPL3 | AR_TYPE_RODATA | AR_S | AR_P);
337 
338 	desc.read_exec_only = 0;
339 	desc.seg_not_present = 1;
340 	install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA | AR_S);
341 
342 	desc.read_exec_only = 1;
343 	desc.limit = 1;
344 	install_valid(&desc, AR_DPL3 | AR_TYPE_RODATA | AR_S);
345 
346 	desc.limit = 0;
347 	desc.base_addr = 1;
348 	install_valid(&desc, AR_DPL3 | AR_TYPE_RODATA | AR_S);
349 
350 	desc.base_addr = 0;
351 	install_invalid(&desc, false);
352 
353 	desc.seg_not_present = 0;
354 	desc.read_exec_only = 0;
355 	desc.seg_32bit = 1;
356 	install_valid(&desc, AR_DPL3 | AR_TYPE_RWDATA | AR_S | AR_P | AR_DB);
357 	install_invalid(&desc, true);
358 }
359 
360 /*
361  * 0: thread is idle
362  * 1: thread armed
363  * 2: thread should clear LDT entry 0
364  * 3: thread should exit
365  */
366 static volatile unsigned int ftx;
367 
368 static void *threadproc(void *ctx)
369 {
370 	cpu_set_t cpuset;
371 	CPU_ZERO(&cpuset);
372 	CPU_SET(1, &cpuset);
373 	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
374 		err(1, "sched_setaffinity to CPU 1");	/* should never fail */
375 
376 	while (1) {
377 		syscall(SYS_futex, &ftx, FUTEX_WAIT, 0, NULL, NULL, 0);
378 		while (ftx != 2) {
379 			if (ftx >= 3)
380 				return NULL;
381 		}
382 
383 		/* clear LDT entry 0 */
384 		const struct user_desc desc = {};
385 		if (syscall(SYS_modify_ldt, 1, &desc, sizeof(desc)) != 0)
386 			err(1, "modify_ldt");
387 
388 		/* If ftx == 2, set it to zero.  If ftx == 100, quit. */
389 		unsigned int x = -2;
390 		asm volatile ("lock xaddl %[x], %[ftx]" :
391 			      [x] "+r" (x), [ftx] "+m" (ftx));
392 		if (x != 2)
393 			return NULL;
394 	}
395 }
396 
397 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
398 		       int flags)
399 {
400 	struct sigaction sa;
401 	memset(&sa, 0, sizeof(sa));
402 	sa.sa_sigaction = handler;
403 	sa.sa_flags = SA_SIGINFO | flags;
404 	sigemptyset(&sa.sa_mask);
405 	if (sigaction(sig, &sa, 0))
406 		err(1, "sigaction");
407 
408 }
409 
410 static jmp_buf jmpbuf;
411 
412 static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
413 {
414 	siglongjmp(jmpbuf, 1);
415 }
416 
417 static void do_multicpu_tests(void)
418 {
419 	cpu_set_t cpuset;
420 	pthread_t thread;
421 	int failures = 0, iters = 5, i;
422 	unsigned short orig_ss;
423 
424 	CPU_ZERO(&cpuset);
425 	CPU_SET(1, &cpuset);
426 	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
427 		printf("[SKIP]\tCannot set affinity to CPU 1\n");
428 		return;
429 	}
430 
431 	CPU_ZERO(&cpuset);
432 	CPU_SET(0, &cpuset);
433 	if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
434 		printf("[SKIP]\tCannot set affinity to CPU 0\n");
435 		return;
436 	}
437 
438 	sethandler(SIGSEGV, sigsegv, 0);
439 #ifdef __i386__
440 	/* True 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults. */
441 	sethandler(SIGILL, sigsegv, 0);
442 #endif
443 
444 	printf("[RUN]\tCross-CPU LDT invalidation\n");
445 
446 	if (pthread_create(&thread, 0, threadproc, 0) != 0)
447 		err(1, "pthread_create");
448 
449 	asm volatile ("mov %%ss, %0" : "=rm" (orig_ss));
450 
451 	for (i = 0; i < 5; i++) {
452 		if (sigsetjmp(jmpbuf, 1) != 0)
453 			continue;
454 
455 		/* Make sure the thread is ready after the last test. */
456 		while (ftx != 0)
457 			;
458 
459 		struct user_desc desc = {
460 			.entry_number    = 0,
461 			.base_addr       = 0,
462 			.limit           = 0xfffff,
463 			.seg_32bit       = 1,
464 			.contents        = 0, /* Data */
465 			.read_exec_only  = 0,
466 			.limit_in_pages  = 1,
467 			.seg_not_present = 0,
468 			.useable         = 0
469 		};
470 
471 		if (safe_modify_ldt(0x11, &desc, sizeof(desc)) != 0) {
472 			if (errno != ENOSYS)
473 				err(1, "modify_ldt");
474 			printf("[SKIP]\tmodify_ldt unavailable\n");
475 			break;
476 		}
477 
478 		/* Arm the thread. */
479 		ftx = 1;
480 		syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
481 
482 		asm volatile ("mov %0, %%ss" : : "r" (0x7));
483 
484 		/* Go! */
485 		ftx = 2;
486 
487 		while (ftx != 0)
488 			;
489 
490 		/*
491 		 * On success, modify_ldt will segfault us synchronously,
492 		 * and we'll escape via siglongjmp.
493 		 */
494 
495 		failures++;
496 		asm volatile ("mov %0, %%ss" : : "rm" (orig_ss));
497 	};
498 
499 	ftx = 100;  /* Kill the thread. */
500 	syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
501 
502 	if (pthread_join(thread, NULL) != 0)
503 		err(1, "pthread_join");
504 
505 	if (failures) {
506 		printf("[FAIL]\t%d of %d iterations failed\n", failures, iters);
507 		nerrs++;
508 	} else {
509 		printf("[OK]\tAll %d iterations succeeded\n", iters);
510 	}
511 }
512 
513 static int finish_exec_test(void)
514 {
515 	/*
516 	 * In a sensible world, this would be check_invalid_segment(0, 1);
517 	 * For better or for worse, though, the LDT is inherited across exec.
518 	 * We can probably change this safely, but for now we test it.
519 	 */
520 	check_valid_segment(0, 1,
521 			    AR_DPL3 | AR_TYPE_XRCODE | AR_S | AR_P | AR_DB,
522 			    42, true);
523 
524 	return nerrs ? 1 : 0;
525 }
526 
527 static void do_exec_test(void)
528 {
529 	printf("[RUN]\tTest exec\n");
530 
531 	struct user_desc desc = {
532 		.entry_number    = 0,
533 		.base_addr       = 0,
534 		.limit           = 42,
535 		.seg_32bit       = 1,
536 		.contents        = 2, /* Code, not conforming */
537 		.read_exec_only  = 0,
538 		.limit_in_pages  = 0,
539 		.seg_not_present = 0,
540 		.useable         = 0
541 	};
542 	install_valid(&desc, AR_DPL3 | AR_TYPE_XRCODE | AR_S | AR_P | AR_DB);
543 
544 	pid_t child = fork();
545 	if (child == 0) {
546 		execl("/proc/self/exe", "ldt_gdt_test_exec", NULL);
547 		printf("[FAIL]\tCould not exec self\n");
548 		exit(1);	/* exec failed */
549 	} else {
550 		int status;
551 		if (waitpid(child, &status, 0) != child ||
552 		    !WIFEXITED(status)) {
553 			printf("[FAIL]\tChild died\n");
554 			nerrs++;
555 		} else if (WEXITSTATUS(status) != 0) {
556 			printf("[FAIL]\tChild failed\n");
557 			nerrs++;
558 		} else {
559 			printf("[OK]\tChild succeeded\n");
560 		}
561 	}
562 }
563 
564 int main(int argc, char **argv)
565 {
566 	if (argc == 1 && !strcmp(argv[0], "ldt_gdt_test_exec"))
567 		return finish_exec_test();
568 
569 	do_simple_tests();
570 
571 	do_multicpu_tests();
572 
573 	do_exec_test();
574 
575 	return nerrs ? 1 : 0;
576 }
577