os161-1.99
 All Data Structures
crash.c
00001 /*
00002  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
00003  *      The President and Fellows of Harvard College.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * crash.c
00032  *
00033  *      Commit a variety of exceptions, primarily address faults.
00034  *
00035  * Once the basic system calls assignment is complete, none of these
00036  * should crash the kernel.
00037  *
00038  * They should all, however, terminate this program, except for the
00039  * one that writes to the code segment. (That one won't cause program
00040  * termination until/unless you implement read-only segments in your
00041  * VM system.)
00042  */
00043 
00044 #include <stdio.h>
00045 #include <stdint.h>
00046 #include <unistd.h>
00047 #include <err.h>
00048 
00049 #if defined(__mips__)
00050 #define KERNEL_ADDR     0x80000000
00051 #define INVAL_ADDR      0x40000000
00052 #define INSN_TYPE       uint32_t
00053 #define INVAL_INSN      0x0000003f
00054 #else
00055 #error "Please fix this"
00056 #endif
00057 
00058 typedef void (*func)(void);
00059 
00060 static
00061 void
00062 read_from_null(void)
00063 {
00064         int *null = NULL;
00065         volatile int x;
00066         x = *null;
00067 }
00068 
00069 static
00070 void
00071 read_from_inval(void)
00072 {
00073         int *ptr = (int *) INVAL_ADDR;
00074         volatile int x;
00075         x = *ptr;
00076 }
00077 
00078 static
00079 void
00080 read_from_kernel(void)
00081 {
00082         int *ptr = (int *) KERNEL_ADDR;
00083         volatile int x;
00084         x = *ptr;
00085 }
00086 
00087 static
00088 void
00089 write_to_null(void)
00090 {
00091         int *null = NULL;
00092         *null = 6;
00093 }
00094 
00095 static
00096 void
00097 write_to_inval(void)
00098 {
00099         int *ptr = (int *) INVAL_ADDR;
00100         *ptr = 8;
00101 }
00102 
00103 static
00104 void
00105 write_to_code(void)
00106 {
00107         INSN_TYPE *x = (INSN_TYPE *)write_to_code;
00108         *x = INVAL_INSN;
00109 }
00110 
00111 static
00112 void
00113 write_to_kernel(void)
00114 {
00115         int *ptr = (int *) KERNEL_ADDR;
00116         *ptr = 8;
00117 }
00118 
00119 static
00120 void
00121 jump_to_null(void)
00122 {
00123         func f = NULL;
00124         f();
00125 }
00126 
00127 static
00128 void
00129 jump_to_inval(void)
00130 {
00131         func f = (func) INVAL_ADDR;
00132         f();
00133 }
00134 
00135 static
00136 void
00137 jump_to_kernel(void)
00138 {
00139         func f = (func) KERNEL_ADDR;
00140         f();
00141 }
00142 
00143 
00144 static
00145 void
00146 illegal_instruction(void)
00147 {
00148 #if defined(__mips__)
00149         asm(".long 0x0000003f");
00150 #else
00151 #error "Please fix this"
00152 #endif
00153 }
00154 
00155 static
00156 void
00157 alignment_error(void)
00158 {
00159         int x;
00160         int *ptr = &x;
00161         int *badptr = (int *)(((char *)ptr)+1);
00162 
00163         volatile int j;
00164         j = *badptr;
00165 }
00166 
00167 static
00168 void
00169 divide_by_zero(void)
00170 {
00171         volatile int x = 6;
00172         volatile int z = 0;
00173         volatile int a;
00174 
00175         a = x/z;
00176 }
00177 
00178 static
00179 void
00180 mod_by_zero(void)
00181 {
00182         volatile int x = 6;
00183         volatile int z = 0;
00184         volatile int a;
00185 
00186         a = x%z;
00187 }
00188 
00189 static
00190 void
00191 recurse_inf(void)
00192 {
00193         volatile char buf[16];
00194         buf[0] = 0;
00195         recurse_inf();
00196         buf[0] = 1;
00197 }
00198 
00199 
00200 static
00201 struct {
00202         int ch;
00203         const char *name;
00204         func f;
00205 } ops[] = {
00206         { 'a', "read from NULL",                read_from_null },
00207         { 'b', "read from invalid address",     read_from_inval },
00208         { 'c', "read from kernel address",      read_from_kernel },
00209         { 'd', "write to NULL",                 write_to_null },
00210         { 'e', "write to invalid address",      write_to_inval },
00211         { 'f', "write to code segment",         write_to_code },
00212         { 'g', "write to kernel address",       write_to_kernel },
00213         { 'h', "jump to NULL",                  jump_to_null },
00214         { 'i', "jump to invalid address",       jump_to_inval },
00215         { 'j', "jump to kernel address",        jump_to_kernel },
00216         { 'k', "alignment error",               alignment_error },
00217         { 'l', "illegal instruction",           illegal_instruction },
00218         { 'm', "divide by zero",                divide_by_zero },
00219         { 'n', "mod by zero",                   mod_by_zero },
00220         { 'o', "Recurse infinitely",            recurse_inf },
00221         { 0, NULL, NULL }
00222 };
00223 
00224 int
00225 main(int argc, char **argv)
00226 {
00227         int op, i, status;
00228         pid_t pid;
00229 
00230         if (argc == 2) {
00231                 op = argv[1][0];
00232         }
00233         else {
00234                 for (i=0; ops[i].name; i++) {
00235                         printf("[%c] %s\n", ops[i].ch, ops[i].name);
00236                 }
00237                 printf("[*] Run everything (in subprocesses)\n");
00238                 printf("Note: [f] may not cause an exception on some "
00239                        "platforms, in which\ncase it'll appear to fail.\n");
00240 
00241                 printf("Choose: ");
00242                 op = getchar();
00243         }
00244 
00245         if (op=='*') {
00246                 for (i=0; ops[i].name; i++) {
00247                         printf("Running: [%c] %s\n", ops[i].ch, ops[i].name);
00248                         pid = fork();
00249                         if (pid<0) {
00250                                 /* error */
00251                                 warn("fork");
00252                         }
00253                         else if (pid==0) {
00254                                 /* child */
00255                                 ops[i].f();
00256                                 printf("I wasn't killed - test fails!\n");
00257                                 _exit(1);
00258                         }
00259                         waitpid(pid, &status, 0);
00260                         if (WIFSIGNALED(status)) {
00261                                 printf("Signal %d\n", WTERMSIG(status));
00262                         }
00263                         else {
00264                                 printf("Exit %d\n", WEXITSTATUS(status));
00265                         }
00266                 }
00267         }
00268         else {
00269                 /* intentionally don't check if op is in bounds :) */
00270                 ops[op-'a'].f();
00271 
00272                 printf("I wasn't killed - test fails!\n");
00273         }
00274   
00275         return 0;
00276 }
 All Data Structures