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