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 }
157