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         volatile int done = 0;
  61 
  62         int rc = getcontext(&ucp);
  63         if (done) {
  64                 (void) getcontext(&ucp);
  65                 return;
  66         }
  67 
  68         if (rc == 0) {
  69                 done = 1;
  70                 ucp.uc_mcontext.gregs[seg] = selector;
  71                 (void) setcontext(&ucp);
  72         }
  73         abort();
  74 }
  75 
  76 static void
  77 resetcs(void)
  78 {
  79         return (resetseg(CS));
  80 }
  81 
  82 static void
  83 resetds(void)
  84 {
  85         return (resetseg(DS));
  86 }
  87 
  88 static void
  89 resetes(void)
  90 {
  91         return (resetseg(ES));
  92 }
  93 
  94 static void
  95 resetfs(void)
  96 {
  97         return (resetseg(FS));
  98 }
  99 
 100 static void
 101 resetgs(void)
 102 {
 103         return (resetseg(GS));
 104 }
 105 
 106 static void
 107 resetss(void)
 108 {
 109         return (resetseg(SS));
 110 }
 111 
 112 static void
 113 inchild(void (*func)())
 114 {
 115         pid_t pid;
 116 
 117         switch ((pid = fork())) {
 118         case 0:
 119                 func();
 120                 exit(0);
 121         case -1:
 122                 exit(1);
 123         default:
 124                 (void) waitpid(pid, NULL, 0);
 125                 return;
 126         }
 127 
 128 }
 129 
 130 int
 131 main(int argc, char *argv[])
 132 {
 133         for (selector = 0; selector < 8194; selector++) {
 134                 inchild(resetcs);
 135                 inchild(resetds);
 136                 inchild(resetes);
 137                 inchild(resetfs);
 138                 inchild(resetgs);
 139                 inchild(resetss);
 140                 inchild(badds);
 141                 inchild(bades);
 142                 inchild(badfs);
 143                 inchild(badgs);
 144                 inchild(badss);
 145         }
 146 
 147         exit(0);
 148 }