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 33 static void badds(void) 34 { 35 __asm__ volatile("movw %0, %%ds" : : "r" (selector)); 36 } 37 38 static void bades(void) 39 { 40 __asm__ volatile("movw %0, %%es" : : "r" (selector)); 41 } 42 43 static void badfs(void) 44 { 45 __asm__ volatile("movw %0, %%fs" : : "r" (selector)); 46 } 47 48 static void badgs(void) 49 { 50 __asm__ volatile("movw %0, %%gs" : : "r" (selector)); 51 } 52 53 static void badss(void) 54 { 55 __asm__ volatile("movw %0, %%ss" : : "r" (selector)); 56 } 57 58 static void 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 79 resetcs(void) 80 { 81 return (resetseg(CS)); 82 } 83 84 static void 85 resetds(void) 86 { 87 return (resetseg(DS)); 88 } 89 90 static void 91 resetes(void) 92 { 93 return (resetseg(ES)); 94 } 95 96 static void 97 resetfs(void) 98 { 99 return (resetseg(FS)); 100 } 101 102 static void 103 resetgs(void) 104 { 105 return (resetseg(GS)); 106 } 107 108 static void 109 resetss(void) 110 { 111 return (resetseg(SS)); 112 } 113 114 static void 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 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