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 2019 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 #include <sys/resource.h>
22 #include <err.h>
23
24 /*
25 * Load a bunch of bad selectors into the seg regs: this will typically cause
26 * the child process to core dump, but it shouldn't panic the kernel...
27 *
28 * It's especially interesting to run this on CPU0.
29 */
30
31 unsigned short selector;
32
badds(void)33 static void badds(void)
34 {
35 __asm__ volatile("movw %0, %%ds" : : "r" (selector));
36 }
37
bades(void)38 static void bades(void)
39 {
40 __asm__ volatile("movw %0, %%es" : : "r" (selector));
41 }
42
badfs(void)43 static void badfs(void)
44 {
45 __asm__ volatile("movw %0, %%fs" : : "r" (selector));
46 }
47
badgs(void)48 static void badgs(void)
49 {
50 __asm__ volatile("movw %0, %%gs" : : "r" (selector));
51 }
52
badss(void)53 static void badss(void)
54 {
55 __asm__ volatile("movw %0, %%ss" : : "r" (selector));
56 }
57
58 static void
resetseg(uint_t seg)59 resetseg(uint_t seg)
60 {
61 ucontext_t ucp;
62 volatile int done = 0;
63
64 int rc = getcontext(&ucp);
65 if (done) {
66 (void) getcontext(&ucp);
67 return;
68 }
69
70 if (rc == 0) {
71 done = 1;
72 ucp.uc_mcontext.gregs[seg] = selector;
73 (void) setcontext(&ucp);
74 }
75 abort();
76 }
77
78 static void
resetcs(void)79 resetcs(void)
80 {
81 return (resetseg(CS));
82 }
83
84 static void
resetds(void)85 resetds(void)
86 {
87 return (resetseg(DS));
88 }
89
90 static void
resetes(void)91 resetes(void)
92 {
93 return (resetseg(ES));
94 }
95
96 static void
resetfs(void)97 resetfs(void)
98 {
99 return (resetseg(FS));
100 }
101
102 static void
resetgs(void)103 resetgs(void)
104 {
105 return (resetseg(GS));
106 }
107
108 static void
resetss(void)109 resetss(void)
110 {
111 return (resetseg(SS));
112 }
113
114 static void
inchild(void (* func)())115 inchild(void (*func)())
116 {
117 pid_t pid;
118
119 switch ((pid = fork())) {
120 case 0:
121 func();
122 exit(EXIT_SUCCESS);
123 case -1:
124 exit(EXIT_FAILURE);
125 default:
126 (void) waitpid(pid, NULL, 0);
127 return;
128 }
129
130 }
131
132 int
main(int argc,char * argv[])133 main(int argc, char *argv[])
134 {
135 struct rlimit rl = { 0, };
136
137 if (setrlimit(RLIMIT_CORE, &rl) != 0) {
138 err(EXIT_FAILURE, "failed to disable cores");
139 }
140
141 for (selector = 0; selector < 512; selector++) {
142 inchild(resetcs);
143 inchild(resetds);
144 inchild(resetes);
145 inchild(resetfs);
146 inchild(resetgs);
147 inchild(resetss);
148 inchild(badds);
149 inchild(bades);
150 inchild(badfs);
151 inchild(badgs);
152 inchild(badss);
153 }
154
155 exit(EXIT_SUCCESS);
156 }
157