1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2018 Joyent, Inc.
14  */
15 
16 #include <stdlib.h>
17 #include <ucontext.h>
18 #include <sys/wait.h>
19 #include <unistd.h>
20 #include <sys/regset.h>
21 
22 /*
23  * Load a bunch of bad selectors into the seg regs: this will typically cause
24  * the child process to core dump, but it shouldn't panic the kernel...
25  *
26  * It's especially interesting to run this on CPU0.
27  */
28 
29 unsigned short selector;
30 
31 static void badds(void)
32 {
33 	__asm__ volatile("movw %0, %%ds" : : "r" (selector));
34 }
35 
36 static void bades(void)
37 {
38 	__asm__ volatile("movw %0, %%es" : : "r" (selector));
39 }
40 
41 static void badfs(void)
42 {
43 	__asm__ volatile("movw %0, %%fs" : : "r" (selector));
44 }
45 
46 static void badgs(void)
47 {
48 	__asm__ volatile("movw %0, %%gs" : : "r" (selector));
49 }
50 
51 static void badss(void)
52 {
53 	__asm__ volatile("movw %0, %%ss" : : "r" (selector));
54 }
55 
56 static void
57 resetseg(uint_t seg)
58 {
59 	ucontext_t ucp;
60 	volatile int done = 0;
61 
62 	int rc = getcontext(&ucp);
63 	if (done) {
64 		(void) getcontext(&ucp);
65 		return;
66 	}
67 
68 	if (rc == 0) {
69 		done = 1;
70 		ucp.uc_mcontext.gregs[seg] = selector;
71 		setcontext(&ucp);
72 	}
73 	abort();
74 }
75 
76 static void
77 resetcs(void)
78 {
79 	return (resetseg(CS));
80 }
81 
82 static void
83 resetds(void)
84 {
85 	return (resetseg(DS));
86 }
87 
88 static void
89 resetes(void)
90 {
91 	return (resetseg(ES));
92 }
93 
94 static void
95 resetfs(void)
96 {
97 	return (resetseg(FS));
98 }
99 
100 static void
101 resetgs(void)
102 {
103 	return (resetseg(GS));
104 }
105 
106 static void
107 resetss(void)
108 {
109 	return (resetseg(SS));
110 }
111 
112 static void
113 inchild(void (*func)())
114 {
115 	pid_t pid;
116 
117 	switch ((pid = fork())) {
118 	case 0:
119 		func();
120 		exit(0);
121 	case -1:
122 		exit(1);
123 	default:
124 		(void) waitpid(pid, NULL, 0);
125 		return;
126 	}
127 
128 }
129 
130 int
131 main(int argc, char *argv[])
132 {
133 	for (selector = 0; selector < 8194; selector++) {
134 		inchild(resetcs);
135 		inchild(resetds);
136 		inchild(resetes);
137 		inchild(resetfs);
138 		inchild(resetgs);
139 		inchild(resetss);
140 		inchild(badds);
141 		inchild(bades);
142 		inchild(badfs);
143 		inchild(badgs);
144 		inchild(badss);
145 	}
146 
147 	exit(0);
148 }
149