1309b04b8SJohn Levon /*
2309b04b8SJohn Levon  * This file and its contents are supplied under the terms of the
3309b04b8SJohn Levon  * Common Development and Distribution License ("CDDL"), version 1.0.
4309b04b8SJohn Levon  * You may only use this file in accordance with the terms of version
5309b04b8SJohn Levon  * 1.0 of the CDDL.
6309b04b8SJohn Levon  *
7309b04b8SJohn Levon  * A full copy of the text of the CDDL should have accompanied this
8309b04b8SJohn Levon  * source.  A copy of the CDDL is also available via the Internet at
9309b04b8SJohn Levon  * http://www.illumos.org/license/CDDL.
10309b04b8SJohn Levon  */
11309b04b8SJohn Levon 
12309b04b8SJohn Levon /*
13dbdc225aSJohn Levon  * Copyright 2019 Joyent, Inc.
14309b04b8SJohn Levon  */
15309b04b8SJohn Levon 
16309b04b8SJohn Levon #include <stdlib.h>
17309b04b8SJohn Levon #include <ucontext.h>
18309b04b8SJohn Levon #include <sys/wait.h>
19309b04b8SJohn Levon #include <unistd.h>
20309b04b8SJohn Levon #include <sys/regset.h>
21dbdc225aSJohn Levon #include <sys/resource.h>
22dbdc225aSJohn Levon #include <err.h>
23309b04b8SJohn Levon 
24309b04b8SJohn Levon /*
25309b04b8SJohn Levon  * Load a bunch of bad selectors into the seg regs: this will typically cause
26309b04b8SJohn Levon  * the child process to core dump, but it shouldn't panic the kernel...
27309b04b8SJohn Levon  *
28309b04b8SJohn Levon  * It's especially interesting to run this on CPU0.
29309b04b8SJohn Levon  */
30309b04b8SJohn Levon 
31309b04b8SJohn Levon unsigned short selector;
32309b04b8SJohn Levon 
badds(void)33309b04b8SJohn Levon static void badds(void)
34309b04b8SJohn Levon {
35309b04b8SJohn Levon 	__asm__ volatile("movw %0, %%ds" : : "r" (selector));
36309b04b8SJohn Levon }
37309b04b8SJohn Levon 
bades(void)38309b04b8SJohn Levon static void bades(void)
39309b04b8SJohn Levon {
40309b04b8SJohn Levon 	__asm__ volatile("movw %0, %%es" : : "r" (selector));
41309b04b8SJohn Levon }
42309b04b8SJohn Levon 
badfs(void)43309b04b8SJohn Levon static void badfs(void)
44309b04b8SJohn Levon {
45309b04b8SJohn Levon 	__asm__ volatile("movw %0, %%fs" : : "r" (selector));
46309b04b8SJohn Levon }
47309b04b8SJohn Levon 
badgs(void)48309b04b8SJohn Levon static void badgs(void)
49309b04b8SJohn Levon {
50309b04b8SJohn Levon 	__asm__ volatile("movw %0, %%gs" : : "r" (selector));
51309b04b8SJohn Levon }
52309b04b8SJohn Levon 
badss(void)53309b04b8SJohn Levon static void badss(void)
54309b04b8SJohn Levon {
55309b04b8SJohn Levon 	__asm__ volatile("movw %0, %%ss" : : "r" (selector));
56309b04b8SJohn Levon }
57309b04b8SJohn Levon 
58309b04b8SJohn Levon static void
resetseg(uint_t seg)59309b04b8SJohn Levon resetseg(uint_t seg)
60309b04b8SJohn Levon {
61309b04b8SJohn Levon 	ucontext_t ucp;
62ba93fbafSToomas Soome 	volatile int done = 0;
63309b04b8SJohn Levon 
64309b04b8SJohn Levon 	int rc = getcontext(&ucp);
65309b04b8SJohn Levon 	if (done) {
66ba93fbafSToomas Soome 		(void) getcontext(&ucp);
67309b04b8SJohn Levon 		return;
68309b04b8SJohn Levon 	}
69309b04b8SJohn Levon 
70ba93fbafSToomas Soome 	if (rc == 0) {
71ba93fbafSToomas Soome 		done = 1;
72ba93fbafSToomas Soome 		ucp.uc_mcontext.gregs[seg] = selector;
73dc5e7685SJohn Levon 		(void) setcontext(&ucp);
74ba93fbafSToomas Soome 	}
75309b04b8SJohn Levon 	abort();
76309b04b8SJohn Levon }
77309b04b8SJohn Levon 
78309b04b8SJohn Levon static void
resetcs(void)79309b04b8SJohn Levon resetcs(void)
80309b04b8SJohn Levon {
81309b04b8SJohn Levon 	return (resetseg(CS));
82309b04b8SJohn Levon }
83309b04b8SJohn Levon 
84309b04b8SJohn Levon static void
resetds(void)85309b04b8SJohn Levon resetds(void)
86309b04b8SJohn Levon {
87309b04b8SJohn Levon 	return (resetseg(DS));
88309b04b8SJohn Levon }
89309b04b8SJohn Levon 
90309b04b8SJohn Levon static void
resetes(void)91309b04b8SJohn Levon resetes(void)
92309b04b8SJohn Levon {
93309b04b8SJohn Levon 	return (resetseg(ES));
94309b04b8SJohn Levon }
95309b04b8SJohn Levon 
96309b04b8SJohn Levon static void
resetfs(void)97309b04b8SJohn Levon resetfs(void)
98309b04b8SJohn Levon {
99309b04b8SJohn Levon 	return (resetseg(FS));
100309b04b8SJohn Levon }
101309b04b8SJohn Levon 
102309b04b8SJohn Levon static void
resetgs(void)103309b04b8SJohn Levon resetgs(void)
104309b04b8SJohn Levon {
105309b04b8SJohn Levon 	return (resetseg(GS));
106309b04b8SJohn Levon }
107309b04b8SJohn Levon 
108309b04b8SJohn Levon static void
resetss(void)109309b04b8SJohn Levon resetss(void)
110309b04b8SJohn Levon {
111309b04b8SJohn Levon 	return (resetseg(SS));
112309b04b8SJohn Levon }
113309b04b8SJohn Levon 
114309b04b8SJohn Levon static void
inchild(void (* func)())115309b04b8SJohn Levon inchild(void (*func)())
116309b04b8SJohn Levon {
117309b04b8SJohn Levon 	pid_t pid;
118309b04b8SJohn Levon 
119309b04b8SJohn Levon 	switch ((pid = fork())) {
120309b04b8SJohn Levon 	case 0:
121309b04b8SJohn Levon 		func();
122dbdc225aSJohn Levon 		exit(EXIT_SUCCESS);
123309b04b8SJohn Levon 	case -1:
124dbdc225aSJohn Levon 		exit(EXIT_FAILURE);
125309b04b8SJohn Levon 	default:
126309b04b8SJohn Levon 		(void) waitpid(pid, NULL, 0);
127309b04b8SJohn Levon 		return;
128309b04b8SJohn Levon 	}
129309b04b8SJohn Levon 
130309b04b8SJohn Levon }
131309b04b8SJohn Levon 
132309b04b8SJohn Levon int
main(int argc,char * argv[])133309b04b8SJohn Levon main(int argc, char *argv[])
134309b04b8SJohn Levon {
135dbdc225aSJohn Levon 	struct rlimit rl = { 0, };
136dbdc225aSJohn Levon 
137dbdc225aSJohn Levon 	if (setrlimit(RLIMIT_CORE, &rl) != 0) {
138dbdc225aSJohn Levon 		err(EXIT_FAILURE, "failed to disable cores");
139dbdc225aSJohn Levon 	}
140dbdc225aSJohn Levon 
141*a8103542SJohn Levon 	for (selector = 0; selector < 512; selector++) {
142309b04b8SJohn Levon 		inchild(resetcs);
143309b04b8SJohn Levon 		inchild(resetds);
144309b04b8SJohn Levon 		inchild(resetes);
145309b04b8SJohn Levon 		inchild(resetfs);
146309b04b8SJohn Levon 		inchild(resetgs);
147309b04b8SJohn Levon 		inchild(resetss);
148309b04b8SJohn Levon 		inchild(badds);
149309b04b8SJohn Levon 		inchild(bades);
150309b04b8SJohn Levon 		inchild(badfs);
151309b04b8SJohn Levon 		inchild(badgs);
152309b04b8SJohn Levon 		inchild(badss);
153309b04b8SJohn Levon 	}
154309b04b8SJohn Levon 
155dbdc225aSJohn Levon 	exit(EXIT_SUCCESS);
156309b04b8SJohn Levon }