From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 31-JUL-1990 00:19:12.20
To:	MRGATE::"ARISIA::EVERHART"
CC:	
Subj:	how to crash a RISC machine from user-mode code: !!!

Received:  by crdgw1.ge.com (5.57/GE 1.70)
	 id AA02754; Mon, 30 Jul 90 23:59:32 EDT
Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Mon, 30 JUL 90 20:46:12 PDT
Received: by ucbvax.Berkeley.EDU (5.63/1.42)
	id AA05292; Mon, 30 Jul 90 20:35:49 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 30 Jul 90 17:47:17 GMT
From: zaphod.mps.ohio-state.edu!usc!samsung!mitech!gjc@tut.cis.ohio-state.edu
Organization: Mitech Corporation, Concord MA
Subject: how to crash a RISC machine from user-mode code: !!!
Message-Id: <4023@mitech.com>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

I am posting this to info-vax because lots of people on this list
would have SUN-4's or other RISC machines to try it on, and we VAX
users could use a good chuckle from time to time.

The motivation here: As I was reading about the SPARC architecture I
thought, gee, it must be quite a pain to do the analysis of all the
billions of different machine-state combinations one could get executing
a sequence of a few random instructions. And I *do* mean random. Not
well behaved stuff like compilers are supposed to generate, but really
random data executed as code. Buggy programs are jumping off into data
space all the time.

Extract this as crashme.c, cc -o crashme crashme.c and then try this:
%crashme 1000 10 200

On the few SUN-4's I've tried: this allows a user-mode program to
crash the system. Is it a hardware bug (hard to fix) or just a
software bug? I don't know. Report back your findings to me
and I will summarize. (Try it with different argument combinations).

/* crashme: Create a string of random bytes and then jump to it.
            crashme <nbytes> <srand> <ntrys>

THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

A signal handler is set up so that in most cases the machine exception
generated by the illegal instructions, bad operands, etc in the procedure
made up of random data are caught; and another round of randomness may
be tried. Eventually the a random instruction may corrupt the program or
the machine state in such a way that the program must halt.

Note: This program has never caused any problem on a VAX, or other CISC
      architecture with a protected-mode operating system, but on certain
      RISC machines it has been observed to allow a user-mode program to
      crash the machine.

*/


#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

long nbytes,nseed,ntrys;
unsigned char *the_data;

jmp_buf again_buff;

void (*badboy)();

void again_handler(sig, code, scp, addr)
     int sig, code;
     struct sigcontext *scp;
     char *addr;
{char *ss;
 switch(sig)
   {case SIGILL: ss =   " illegal instruction"; break;
    case SIGTRAP: ss =   " trace trap"; break;
    case SIGFPE: ss =   " arithmetic exception"; break;
    case SIGBUS: ss =  " bus error"; break;
    case SIGSEGV: ss =  " segmentation violation"; break;
   default: ss = "";}
 fprintf(stderr,"Got signal %d%s\n",sig,ss);
 longjmp(again_buff,3);}
 

set_up_signals()
{signal(SIGILL,again_handler);
 signal(SIGTRAP,again_handler);
 signal(SIGFPE,again_handler);
 signal(SIGBUS,again_handler);
 signal(SIGSEGV,again_handler);}

compute_badboy()
{long j,n;
 n = (nbytes < 0) ? - nbytes : nbytes;
 for(j=0;j<n;++j) the_data[j] = (rand() >> 7) & 0xFF;
 if (nbytes < 0)
   {fprintf(stdout,"Dump of %ld bytes of data\n",n);
    for(j=0;j<n;++j)
      {fprintf(stdout,"%3d",the_data[j]);
       if ((j % 20) == 19) putc('\n',stdout); else putc(' ',stdout);}
    putc('\n',stdout);}}

try_one_crash()
{compute_badboy();
 if (nbytes >= 0) 
   (*badboy)();}
 
main(argc,argv)
 int argc; char **argv;
{long i;
 if (argc != 4) {fprintf(stderr,"crashme <nbytes> <srand> <ntrys>\n");
		 exit(1);}
 nbytes = atol(argv[1]);
 nseed = atol(argv[2]);
 ntrys = atol(argv[3]);
 fprintf(stdout,"crashem %ld %ld %ld\n",nbytes,nseed,ntrys);
 fflush(stdout);
 the_data = (unsigned char *) malloc((nbytes < 0) ? -nbytes : nbytes);
 badboy = (void (*)()) the_data;
 fprintf(stdout,"Badboy at %d. 0x%X\n",badboy,badboy);
 srand(nseed);
 for(i=0;i<ntrys;++i)
   {fprintf(stderr,"%ld\n",i);
    if(setjmp(again_buff) == 3)
      fprintf(stderr,"Barfed\n");
    else
      {set_up_signals();
       try_one_crash();
       fprintf(stderr,"didn't barf!\n");}}}
      

-----end of crashme.c---------- 

