crasher.c revision 6694d3e3d5b7ca2418bbca3007ad4b980f3a3602
1 2//#include <cutils/misc.h> 3 4#include <unistd.h> 5#include <stdio.h> 6#include <stdlib.h> 7#include <string.h> 8#include <sched.h> 9#include <errno.h> 10 11#include <signal.h> 12#include <sys/ptrace.h> 13#include <sys/wait.h> 14#include <sys/socket.h> 15 16#include <pthread.h> 17 18#include <cutils/sockets.h> 19 20extern const char* __progname; 21 22void crash1(void); 23void crashnostack(void); 24static int do_action(const char* arg); 25 26static void maybeabort() { 27 if(time(0) != 42) { 28 abort(); 29 } 30} 31 32static int smash_stack(int i) { 33 printf("crasher: deliberately corrupting stack...\n"); 34 // Unless there's a "big enough" buffer on the stack, gcc 35 // doesn't bother inserting checks. 36 char buf[8]; 37 // If we don't write something relatively unpredictable 38 // into the buffer and then do something with it, gcc 39 // optimizes everything away and just returns a constant. 40 *(int*)(&buf[7]) = (uintptr_t) &buf[0]; 41 return *(int*)(&buf[0]); 42} 43 44static void* global = 0; // So GCC doesn't optimize the tail recursion out of overflow_stack. 45 46__attribute__((noinline)) static void overflow_stack(void* p) { 47 void* buf[1]; 48 buf[0] = p; 49 global = buf; 50 overflow_stack(&buf); 51} 52 53static void test_call1() 54{ 55 *((int*) 32) = 1; 56} 57 58static void *noisy(void *x) 59{ 60 char c = (unsigned) x; 61 for(;;) { 62 usleep(250*1000); 63 write(2, &c, 1); 64 if(c == 'C') *((unsigned*) 0) = 42; 65 } 66 return 0; 67} 68 69static int ctest() 70{ 71 pthread_t thr; 72 pthread_attr_t attr; 73 pthread_attr_init(&attr); 74 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 75 pthread_create(&thr, &attr, noisy, (void*) 'A'); 76 pthread_create(&thr, &attr, noisy, (void*) 'B'); 77 pthread_create(&thr, &attr, noisy, (void*) 'C'); 78 for(;;) ; 79 return 0; 80} 81 82static void* thread_callback(void* raw_arg) 83{ 84 return (void*) do_action((const char*) raw_arg); 85} 86 87static int do_action_on_thread(const char* arg) 88{ 89 pthread_t t; 90 pthread_create(&t, NULL, thread_callback, (void*) arg); 91 void* result = NULL; 92 pthread_join(t, &result); 93 return (int) result; 94} 95 96__attribute__((noinline)) static int crash3(int a) { 97 *((int*) 0xdead) = a; 98 return a*4; 99} 100 101__attribute__((noinline)) static int crash2(int a) { 102 a = crash3(a) + 2; 103 return a*3; 104} 105 106__attribute__((noinline)) static int crash(int a) { 107 a = crash2(a) + 1; 108 return a*2; 109} 110 111static void abuse_heap() { 112 char buf[16]; 113 free((void*) buf); // GCC is smart enough to warn about this, but we're doing it deliberately. 114} 115 116static int do_action(const char* arg) 117{ 118 fprintf(stderr,"crasher: init pid=%d tid=%d\n", getpid(), gettid()); 119 120 if (!strncmp(arg, "thread-", strlen("thread-"))) { 121 return do_action_on_thread(arg + strlen("thread-")); 122 } else if (!strcmp(arg,"smash-stack")) { 123 return smash_stack(42); 124 } else if (!strcmp(arg,"stack-overflow")) { 125 overflow_stack(NULL); 126 } else if (!strcmp(arg,"nostack")) { 127 crashnostack(); 128 } else if (!strcmp(arg,"ctest")) { 129 return ctest(); 130 } else if (!strcmp(arg,"exit")) { 131 exit(1); 132 } else if (!strcmp(arg,"crash")) { 133 return crash(42); 134 } else if (!strcmp(arg,"abort")) { 135 maybeabort(); 136 } else if (!strcmp(arg, "heap-usage")) { 137 abuse_heap(); 138 } 139 140 fprintf(stderr, "%s OP\n", __progname); 141 fprintf(stderr, "where OP is:\n"); 142 fprintf(stderr, " smash-stack overwrite a stack-guard canary\n"); 143 fprintf(stderr, " stack-overflow recurse until the stack overflows\n"); 144 fprintf(stderr, " heap-corruption cause a libc abort by corrupting the heap\n"); 145 fprintf(stderr, " heap-usage cause a libc abort by abusing a heap function\n"); 146 fprintf(stderr, " nostack crash with a NULL stack pointer\n"); 147 fprintf(stderr, " ctest (obsoleted by thread-crash?)\n"); 148 fprintf(stderr, " exit call exit(1)\n"); 149 fprintf(stderr, " crash cause a SIGSEGV\n"); 150 fprintf(stderr, " abort call abort()\n"); 151 fprintf(stderr, "prefix any of the above with 'thread-' to not run\n"); 152 fprintf(stderr, "on the process' main thread.\n"); 153 return EXIT_SUCCESS; 154} 155 156int main(int argc, char **argv) 157{ 158 fprintf(stderr,"crasher: built at " __TIME__ "!@\n"); 159 160 if(argc > 1) { 161 return do_action(argv[1]); 162 } else { 163 crash1(); 164 } 165 166 return 0; 167} 168