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 /* 13*dbdc225aSJohn 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> 21*dbdc225aSJohn Levon #include <sys/resource.h> 22*dbdc225aSJohn 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 33309b04b8SJohn Levon static void badds(void) 34309b04b8SJohn Levon { 35309b04b8SJohn Levon __asm__ volatile("movw %0, %%ds" : : "r" (selector)); 36309b04b8SJohn Levon } 37309b04b8SJohn Levon 38309b04b8SJohn Levon static void bades(void) 39309b04b8SJohn Levon { 40309b04b8SJohn Levon __asm__ volatile("movw %0, %%es" : : "r" (selector)); 41309b04b8SJohn Levon } 42309b04b8SJohn Levon 43309b04b8SJohn Levon static void badfs(void) 44309b04b8SJohn Levon { 45309b04b8SJohn Levon __asm__ volatile("movw %0, %%fs" : : "r" (selector)); 46309b04b8SJohn Levon } 47309b04b8SJohn Levon 48309b04b8SJohn Levon static void badgs(void) 49309b04b8SJohn Levon { 50309b04b8SJohn Levon __asm__ volatile("movw %0, %%gs" : : "r" (selector)); 51309b04b8SJohn Levon } 52309b04b8SJohn Levon 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 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 79309b04b8SJohn Levon resetcs(void) 80309b04b8SJohn Levon { 81309b04b8SJohn Levon return (resetseg(CS)); 82309b04b8SJohn Levon } 83309b04b8SJohn Levon 84309b04b8SJohn Levon static void 85309b04b8SJohn Levon resetds(void) 86309b04b8SJohn Levon { 87309b04b8SJohn Levon return (resetseg(DS)); 88309b04b8SJohn Levon } 89309b04b8SJohn Levon 90309b04b8SJohn Levon static void 91309b04b8SJohn Levon resetes(void) 92309b04b8SJohn Levon { 93309b04b8SJohn Levon return (resetseg(ES)); 94309b04b8SJohn Levon } 95309b04b8SJohn Levon 96309b04b8SJohn Levon static void 97309b04b8SJohn Levon resetfs(void) 98309b04b8SJohn Levon { 99309b04b8SJohn Levon return (resetseg(FS)); 100309b04b8SJohn Levon } 101309b04b8SJohn Levon 102309b04b8SJohn Levon static void 103309b04b8SJohn Levon resetgs(void) 104309b04b8SJohn Levon { 105309b04b8SJohn Levon return (resetseg(GS)); 106309b04b8SJohn Levon } 107309b04b8SJohn Levon 108309b04b8SJohn Levon static void 109309b04b8SJohn Levon resetss(void) 110309b04b8SJohn Levon { 111309b04b8SJohn Levon return (resetseg(SS)); 112309b04b8SJohn Levon } 113309b04b8SJohn Levon 114309b04b8SJohn Levon static void 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(); 122*dbdc225aSJohn Levon exit(EXIT_SUCCESS); 123309b04b8SJohn Levon case -1: 124*dbdc225aSJohn 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 133309b04b8SJohn Levon main(int argc, char *argv[]) 134309b04b8SJohn Levon { 135*dbdc225aSJohn Levon struct rlimit rl = { 0, }; 136*dbdc225aSJohn Levon 137*dbdc225aSJohn Levon if (setrlimit(RLIMIT_CORE, &rl) != 0) { 138*dbdc225aSJohn Levon err(EXIT_FAILURE, "failed to disable cores"); 139*dbdc225aSJohn Levon } 140*dbdc225aSJohn Levon 141309b04b8SJohn Levon for (selector = 0; selector < 8194; 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 155*dbdc225aSJohn Levon exit(EXIT_SUCCESS); 156309b04b8SJohn Levon } 157