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