int main(int argc, const char *argv[]) { # if defined(UNIX) intercept_signal(SIGSEGV, (handler_3_t)&handle_signal, false); intercept_signal(SIGILL, (handler_3_t)&handle_signal, false); # elif defined(WINDOWS) SetUnhandledExceptionFilter(&handle_exception); # endif print("drreg-test running\n"); test_asm(); /* Test fault reg restore */ if (SIGSETJMP(mark) == 0) { test_asm_faultA(); } /* Test fault aflags restore */ if (SIGSETJMP(mark) == 0) { test_asm_faultB(); } /* XXX i#511: add more fault tests and other tricky corner cases */ print("drreg-test finished\n"); return 0; }
int main(void) { INIT(); #ifdef UNIX intercept_signal(SIGSEGV, signal_handler, false); intercept_signal(SIGILL, signal_handler, false); #else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) our_top_handler); #endif test_code_self_mod(); #ifdef X64 test_mov_abs(); #endif test_sandbox_cross_page(); test_sandbox_last_byte(); test_sandbox_fault(); test_sandbox_cti_tgt(); return 0; }
int main(int argc, char **argv) { pthread_t thread0, thread1; void *retval; #if 0 /* Get the number of intervals */ if (argc != 2) { print("Usage: %s <intervals>\n", argv[0]); exit(0); } intervals = atoi(argv[1]); #else /* for batch mode */ intervals = 10; #endif /* Initialize the lock on pi */ pthread_mutex_init(&pi_lock, NULL); intercept_signal(SIGUSR1, signal_handler, false); intercept_signal(SIGSEGV, signal_handler, false); /* Make the two threads */ if (pthread_create(&thread0, NULL, process, (void *)"0") || pthread_create(&thread1, NULL, process, (void *)"1")) { print("%s: cannot make thread\n", argv[0]); exit(1); } /* Join (collapse) the two threads */ if (pthread_join(thread0, &retval) || pthread_join(thread1, &retval)) { print("%s: thread join failed\n", argv[0]); exit(1); } #if VERBOSE print("thread %d sending SIGUSR1\n", getpid()); #endif kill(getpid(), SIGUSR1); #if VERBOSE print("thread %d hitting SIGSEGV\n", getpid()); #endif if (SIGSETJMP(mark) == 0) { *(int *)42 = 0; } /* Print the result */ print("Estimation of pi is %16.15f\n", pi); struct timespec sleeptime; sleeptime.tv_sec = 0; sleeptime.tv_nsec = 1000 * 1000 * 1000; /* 100ms */ nanosleep(&sleeptime, NULL); }
int main() { INIT(); #ifdef UNIX intercept_signal(SIGSEGV, (handler_3_t)signal_handler, false); #else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)custom_top_handler); #endif print("starting good function\n"); twofoo(); print("starting bad function\n"); invalid_ret(1); /* zero page */ invalid_ret(0); /* NULL */ invalid_ret(0x00badbad); /* user mode */ invalid_ret(0x7fffffff); /* user mode */ invalid_ret(0x80000000); /* kernel addr */ invalid_ret(0xbadbad00); /* kernel addr */ invalid_ret(0xfffffffe); /* just bad */ invalid_ret(0xffffffff); /* just bad */ print("all done [not seen]\n"); }
int main(int argc, const char *argv[]) { int arg_offs = 1; long long counter = 0; while (arg_offs < argc && argv[arg_offs][0] == '-') { if (strcmp(argv[arg_offs], "-v") == 0) { /* enough verbosity to satisfy runall.cmake: needs an initial and a * final line */ fprintf(stderr, "starting\n"); intercept_signal(SIGTERM, (handler_3_t) signal_handler, false); arg_offs++; } else return 1; } while (1) { /* workaround for PR 213040: prevent loop from being coarse */ volatile int x = getpid(); /* don't spin forever to avoid hosing machines if test harness somehow * fails to kill. 15 billion syscalls takes ~ 1 minute. */ counter++; if (counter > 15*1024*1024*1024LL) break; } return 0; }
int main() { #ifdef UNIX intercept_signal(SIGSEGV, signal_handler); #else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) our_top_handler); #endif test_leaks(); test_basic(); test_exception(); test_mismatch_dtr(); test_mismatch_int(); std::cout << "bye" << std::endl; /* mismatches above end up causing RtlpCoalesceFreeBlocks to crash resulting * in failing app exit code: simpler to just exit */ exit(0); return 0; }
int main(int argc, char *argv[]) { double res = 0.; #ifdef USE_DYNAMO dynamorio_app_init(); dynamorio_app_start(); #endif #ifdef LINUX intercept_signal(SIGSEGV, signal_handler); #else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) our_top_handler); #endif print("Segfault about to happen\n"); *((volatile int *)0) = 4; print("SHOULD NEVER GET HERE\n"); #ifdef USE_DYNAMO dynamorio_app_stop(); dynamorio_app_exit(); #endif return 0; }
int main() { #ifdef UNIX intercept_signal(SIGSEGV, signal_handler); intercept_signal(SIGBUS, signal_handler); #else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) our_top_handler); #endif fprintf(stderr, "starting\n"); fprintf(stderr, "generating SIGSEGV\n"); fflush(stderr); test_fault_asm(xax_val); return 0; }
int main(int argc, char **argv) { HANDLE lib; HANDLE event; ULONG_PTR hThread; int reloaded = 0; USE_USER32(); #ifdef UNIX /* though win32/ */ intercept_signal(SIGSEGV, signal_handler); #else /* note that can't normally if we have a debugger attached this * will not get this executed */ SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)our_top_handler); #endif event = CreateEvent(NULL, TRUE, FALSE, NULL); hThread = _beginthreadex(NULL, 0, run_func, event, 0, NULL); /* need to run as long as necessary to hit the required faults */ while (transitions < NUM_TRANSITIONS) { lib = LoadLibrary("win32.reload-race.dll.dll"); if (lib == NULL) { print("error loading library\n"); break; } else { reloaded++; #if VERBOSE print("reloaded %d times %d\n", reloaded); #endif import1 = (funptr)GetProcAddress(lib, (LPCSTR) "import_me1"); import2 = (funptr)GetProcAddress(lib, (LPCSTR) "import_me2"); /* may want to explicitly sleep here but that may be slower */ if (reloaded % 2 == 0) YIELD(); FreeLibrary(lib); if (reloaded % 3 == 0) YIELD(); } } SetEvent(event); WaitForSingleObject((HANDLE)hThread, INFINITE); print("main loop done\n"); check_mem_usage(); #if VERBOSE print("reloaded %d times %d\n", reloaded); #endif return 0; }
void * process(void *arg) { char *id = (char *) arg; register double width, localsum; register int i; register int iproc; #if VERBOSE print("thread %s starting\n", id); #endif if (id[0] == '1') { intercept_signal(SIGUSR1, (handler_3_t) SIG_IGN, false); #if VERBOSE print("thread %d ignoring SIGUSR1\n", getpid()); #endif } #if VERBOSE print("thread %d sending SIGUSR1\n", getpid()); #endif kill(getpid(), SIGUSR1); iproc = (*id - '0'); /* Set width */ width = 1.0 / intervals; /* Do the local computations */ localsum = 0; for (i=iproc; i<intervals; i+=2) { register double x = (i + 0.5) * width; localsum += 4.0 / (1.0 + x * x); } localsum *= width; /* Lock pi for update, update it, and unlock */ pthread_mutex_lock(&pi_lock); pi += localsum; pthread_mutex_unlock(&pi_lock); #if VERBOSE print("thread %s exiting\n", id); #endif return(NULL); }
int main(void) { /* XXX: We can also trigger a segfault by trying to execute the buffer. We could * get the address of the buffer in the app using some annotation-based approach. */ #if defined(UNIX) pthread_t thread; intercept_signal(SIGSEGV, (handler_3_t)&handle_signal, false); #elif defined(WINDOWS) HANDLE thread; DWORD threadId; SetUnhandledExceptionFilter(&handle_exception); #endif print("Starting drx_buf threaded test\n"); #if defined(UNIX) CHECK(!pthread_create(&thread, NULL, thread_asm_test, NULL), "create failed"); /* make sure that the buffers are threadsafe */ (void)thread_asm_test(NULL); CHECK(!pthread_join(thread, NULL), "join failed"); #elif defined(WINDOWS) CHECK((thread = CreateThread(NULL, 0, thread_asm_test, NULL, 0, &threadId)) != NULL, "CreateThread failed"); /* make sure that the buffers are threadsafe */ (void)thread_asm_test(NULL); WaitForSingleObject(thread, INFINITE); CloseHandle(thread); #endif print("Ending drx_buf threaded test\n"); print("Starting drx_buf signal test\n"); /* try to cause a segfault and make sure it didn't trigger the buffer to dump */ if (SIGSETJMP(mark) == 0) { int *x = NULL; return *x; } print("Ending drx_buf signal test\n"); return 0; }
int main(int argc, const char *argv[]) { intercept_signal(SIGSEGV, signal_handler, true/*sigstack*/); print("pre-DR init\n"); dr_app_setup(); assert(!dr_app_running_under_dynamorio()); dr_app_start(); assert(dr_app_running_under_dynamorio()); if (do_some_work() < 0) print("error in computation\n"); print("pre-DR stop\n"); dr_app_stop_and_cleanup(); assert(!dr_app_running_under_dynamorio()); print("all done\n"); return 0; }
int main(int argc, const char *argv[]) { int arg_offs = 1; while (arg_offs < argc && argv[arg_offs][0] == '-') { if (strcmp(argv[arg_offs], "-v") == 0) { /* enough verbosity to satisfy runall.cmake: needs an initial and a * final line */ fprintf(stderr, "starting\n"); intercept_signal(SIGTERM, signal_handler); arg_offs++; } else return 1; } while (1) { /* workaround for PR 213040: prevent loop from being coarse */ volatile int x = getpid(); } return 0; }
int main() { uint i; uint writes = 0; byte *DR_base; INIT(); #ifdef USE_DYNAMO dynamorio_app_init(); dynamorio_app_start(); #endif #ifdef UNIX intercept_signal(SIGSEGV, (handler_3_t) signal_handler, false); #else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) our_top_handler); #endif where = setjmp(mark); if (where == 0) { DR_base = get_DR_base(); #if VERBOSE print("DR base is "PFX"\n", DR_base); #endif for (i=0; i<DATASEC_NUM; i++) { byte *start, *end, *pc; bool found = get_named_section_bounds(DR_base, /*FIXME use drmarker to find*/ datasec_names[i], &start, &end); assert(found); #if VERBOSE print("data section %s: "PFX"-"PFX"\n", datasec_names[i], start, end); #endif print("about to write to every page in %s\n", datasec_names[i]); for (pc = start; pc < end; pc += PAGE_SIZE) { /* try to write to every single page */ where = setjmp(mark); if (where == 0) { uint old = *((uint *)pc); *((uint *)pc) = 0x0badbad0; /* restore in same bb so we don't crash DR */ *((uint *)pc) = old; /* if the section is protected we shouldn't get here */ writes++; #if VERBOSE print("successfully wrote to "PFX" in %s!\n", pc, datasec_names[i]); #endif } } #if VERBOSE print("successfully wrote to %d pages!\n", writes); #endif if (writes > 0) print("successfully wrote to %s\n", datasec_names[i]); } } else { print("no DR or no data sections found: are you running natively?\n"); } print("all done\n"); #ifdef USE_DYNAMO dynamorio_app_stop(); dynamorio_app_exit(); #endif }
int main(int argc, char *argv[]) { double res = 0.; int i; #ifndef X64 int j; #endif char *buf; #ifdef LINUX stack_t sigstack; #endif #ifdef USE_DYNAMO dynamorio_app_init(); dynamorio_app_start(); #endif #ifdef LINUX /* our modrm16 tests clobber esp so we need an alternate stack */ sigstack.ss_sp = (char *) malloc(ALT_STACK_SIZE); sigstack.ss_size = ALT_STACK_SIZE; sigstack.ss_flags = SS_ONSTACK; i = sigaltstack(&sigstack, NULL); assert(i == 0); intercept_signal(SIGILL, signal_handler); intercept_signal(SIGSEGV, signal_handler); #else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) our_top_handler); #endif buf = allocate_mem(7*256+1, ALLOW_READ|ALLOW_WRITE|ALLOW_EXEC); assert(buf != NULL); #ifndef X64 print("Jumping to a sequence of every addr16 modrm byte\n"); for (j=0; j<256; j++) { int mod = ((j >> 6) & 0x3); /* top 2 bits */ int reg = ((j >> 3) & 0x7); /* middle 3 bits */ int rm = (j & 0x7); /* bottom 3 bits */ # if defined(LINUX) || defined(X64) buf[j*7 + 0] = 0x65; /* gs: */ # else buf[j*7 + 0] = 0x64; /* fs: */ # endif buf[j*7 + 1] = 0x67; /* addr16 */ buf[j*7 + 2] = 0x8b; /* load */ # ifdef WINDOWS /* Windows can't handle stack pointer being off */ if (reg == 4) { /* xsp */ buf[j*7 + 3] = j | 0x8; } else buf[j*7 + 3] = j; /* nearly every single modrm byte */ # else buf[j*7 + 3] = j; /* every single modrm byte */ # endif if (mod == 1) { buf[j*7 + 4] = 0x03; /* disp */ buf[j*7 + 5] = 0xc3; } else if (mod == 2 || (mod == 0 && rm == 6)) { buf[j*7 + 4] = 0x03; /* disp */ buf[j*7 + 5] = 0x00; /* disp */ } else { buf[j*7 + 4] = 0xc3; /* ret */ buf[j*7 + 5] = 0xc3; } buf[j*7 + 6] = 0xc3; } buf[256*7] = 0xcc; print_access_vio = false; for (j=0; j<256; j++) { i = setjmp(mark); if (i == 0) test_modrm16(&buf[j*7]); else continue; } print("Done with modrm test: tested %d\n", j); count = 0; print_access_vio = true; #endif /* !X64 */ /* multi-byte nop tests (case 9862) */ i = setjmp(mark); if (i == 0) { print("Testing nops\n"); test_nops(); print("Done with nops\n"); } /* SSE3 and 3DNow instrs will not run on all processors so we can't have this * regression test fully test everything: for now its main use is running * manually on the proper machines, or manually verifying decoding of these, * but we'll leave as a suite/ regression test. */ /* SSE3 tests: mostly w/ modrm of (%edx) */ i = setjmp(mark); if (i == 0) { print("Testing SSE3\n"); test_sse3(buf); print("Should not get here\n"); } /* 3D-Now tests: mostly w/ modrm of (%ebx) */ i = setjmp(mark); if (i == 0) { print("Testing 3D-Now\n"); test_3dnow(buf); print("Should not get here\n"); } /* case 6962: far call/jmp tests * Note that DR currently gets the target address wrong for all of these * since we skip the segment and only care about the address: * not going to fix that anytime soon. */ print("Testing far call/jmp\n"); test_far_cti(); /* PR 242815: data16 mbr */ print("Testing data16 mbr\n"); test_data16_mbr(); #ifdef LINUX free(sigstack.ss_sp); #endif print("All done\n"); #ifdef USE_DYNAMO dynamorio_app_stop(); dynamorio_app_exit(); #endif return 0; }
int main(int argc, char *argv[]) { double res = 0.; int i, j; #if defined(USE_DYNAMO) || USE_TIMER || USE_SIGSTACK int rc; #endif #if USE_SIGSTACK stack_t sigstack; #endif #if USE_TIMER struct itimerval t; #endif #ifdef USE_DYNAMO rc = dynamorio_app_init(); ASSERT_NOERR(rc); dynamorio_app_start(); #endif #if USE_TIMER intercept_signal(SIGVTALRM, (handler_t) signal_handler); t.it_interval.tv_sec = 0; t.it_interval.tv_usec = 10000; t.it_value.tv_sec = 0; t.it_value.tv_usec = 10000; rc = setitimer(ITIMER_VIRTUAL, &t, NULL); ASSERT_NOERR(rc); #endif #if USE_SIGSTACK sigstack.ss_sp = (char *) malloc(ALT_STACK_SIZE); sigstack.ss_size = ALT_STACK_SIZE; sigstack.ss_flags = SS_ONSTACK; rc = sigaltstack(&sigstack, NULL); ASSERT_NOERR(rc); # if VERBOSE fprintf(stderr, "Set up sigstack: 0x%08x - 0x%08x\n", sigstack.ss_sp, sigstack.ss_sp + sigstack.ss_size); # endif #endif intercept_signal(SIGSEGV, (handler_t) signal_handler); intercept_signal(SIGUSR1, (handler_t) signal_handler); intercept_signal(SIGUSR2, (handler_t) SIG_IGN); res = cos(0.56); fprintf(stderr, "Sending SIGUSR2\n"); kill(getpid(), SIGUSR2); fprintf(stderr, "Sending SIGUSR1\n"); kill(getpid(), SIGUSR1); #if USE_SIGSTACK /* now remove alt stack */ free(sigstack.ss_sp); sigstack.ss_sp = 0; sigstack.ss_size = 0; sigstack.ss_flags = SS_DISABLE; rc = sigaltstack(&sigstack, NULL); ASSERT_NOERR(rc); #endif fprintf(stderr, "Generating SIGSEGV\n"); #if USE_LONGJMP res = setjmp(env); if (res == 0) { *((int *)0) = 4; } #else kill(getpid(), SIGSEGV); #endif for (i=0; i<ITERS; i++) { if (i % 2 == 0) { res += cos(1./(double)(i+1)); } else { res += sin(1./(double)(i+1)); } j = (i << 4) / (i | 0x38); a[i] += j; } fprintf(stderr, "%f\n", res); #if USE_TIMER memset(&t, 0, sizeof(t)); rc = setitimer(ITIMER_VIRTUAL, &t, NULL); ASSERT_NOERR(rc); if (timer_hits == 0) fprintf(stderr, "Got 0 timer hits!\n"); else fprintf(stderr, "Got some timer hits!\n"); #endif #ifdef USE_DYNAMO dynamorio_app_stop(); dynamorio_app_exit(); #endif return 0; }
int main(int argc, char *argv[]) { int rc; struct itimerval t; struct rusage ru; int arg_offs = 1; if (argc < 2) { return usage(argv[0]); } while (argv[arg_offs][0] == '-') { if (strcmp(argv[arg_offs], "-s") == 0) { if (argc <= arg_offs+1) return usage(argv[0]); limit = atoi(argv[arg_offs+1]); arg_offs += 2; } else if (strcmp(argv[arg_offs], "-m") == 0) { if (argc <= arg_offs+1) return usage(argv[0]); limit = atoi(argv[arg_offs+1])*60; arg_offs += 2; } else if (strcmp(argv[arg_offs], "-h") == 0) { if (argc <= arg_offs+1) return usage(argv[0]); limit = atoi(argv[arg_offs+1])*3600; arg_offs += 2; } else if (strcmp(argv[arg_offs], "-v") == 0) { /* just ignore -v, only here for compatibility with texec */ arg_offs += 1; } else if (strcmp(argv[arg_offs], "-silent") == 0) { silent = 1; arg_offs += 1; } else if (strcmp(argv[arg_offs], "-env") == 0) { if (argc <= arg_offs+2) return usage(argv[0]); #if VERBOSE fprintf(FP, "setting env var \"%s\" to \"%s\"\n", argv[arg_offs+1], argv[arg_offs+2]); #endif rc = setenv(argv[arg_offs+1], argv[arg_offs+2], 1/*overwrite*/); if (rc != 0 || strcmp(getenv(argv[arg_offs+1]), argv[arg_offs+2]) != 0) { fprintf(FP, "error in setenv of \"%s\" to \"%s\"\n", argv[arg_offs+1], argv[arg_offs+2]); fprintf(FP, "setenv returned %d\n", rc); fprintf(FP, "env var \"%s\" is now \"%s\"\n", argv[arg_offs+1], getenv(argv[arg_offs+1])); exit(-1); } arg_offs += 3; } else { return usage(argv[0]); } if (limit < 0) { return usage(argv[0]); } if (argc - arg_offs < 1) return usage(argv[0]); } gettimeofday(&start, (struct timezone *) 0); child = fork(); if (child < 0) { perror("ERROR on fork"); return 1; } else if (child > 0) { pid_t result; int status; get_mem_stats(child); intercept_signal(SIGALRM, (handler_t) signal_handler); intercept_signal(SIGCHLD, (handler_t) signal_handler); t.it_interval.tv_sec = 0; t.it_interval.tv_usec = 500000; t.it_value.tv_sec = 0; t.it_value.tv_usec = 500000; /* must use real timer so timer decrements while process suspended */ rc = setitimer(ITIMER_REAL, &t, NULL); assert(rc == 0); #if VERBOSE fprintf(FP, "parent waiting for child\n"); #endif /* need loop since SIGALRM will interrupt us */ do { result = wait3(&status, 0, &ru); } while (result != child); gettimeofday(&end, (struct timezone *) 0); #if VERBOSE fprintf(FP, "child has exited\n"); #endif /* turn off timer */ t.it_interval.tv_usec = 0; t.it_value.tv_usec = 0; rc = setitimer(ITIMER_REAL, &t, NULL); assert(rc == 0); if (!silent) print_stats(&start, &end, &ru, status); return (status == 0 ? 0 : 1); } else { int result; result = execvp(argv[arg_offs], argv+arg_offs); if (result < 0) { perror("ERROR in execvp"); fprintf(FP, " trying to run %s\n", argv[arg_offs]); return 1; } } return 0; }
int main(int argc, char *argv[]) { double res = 0.; int i; #ifdef USE_DYNAMO dynamorio_app_init(); dynamorio_app_start(); #endif #ifdef LINUX intercept_signal(SIGILL, signal_handler); intercept_signal(SIGSEGV, signal_handler); #else # ifdef X64_DEBUGGER /* FIXME: the vectored handler works fine in the debugger, but natively * the app crashes here: yet the SetUnhandled hits infinite fault loops * in the debugger, and works fine natively! */ AddVectoredExceptionHandler(1/*first*/, (PVECTORED_EXCEPTION_HANDLER) our_top_handler); # else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) our_top_handler); # endif #endif /* privileged instructions */ print("Privileged instructions about to happen\n"); count = 0; i = setjmp(mark); switch (i) { case 0: test_priv_0(); case 1: test_priv_1(); case 2: test_priv_2(); case 3: test_priv_3(); } /* prefix tests */ print("OK instr about to happen\n"); /* multiple prefixes */ /* FIXME: actually these prefixes on a jmp are "reserved" but this seems to work */ test_prefix_0(); print("Bad instr about to happen\n"); /* lock prefix, which is illegal instruction if placed on jmp */ count = 0; invalid_lock = true; if (setjmp(mark) == 0) { test_prefix_1(); } invalid_lock = false; print("Invalid instructions about to happen\n"); count = 0; i = setjmp(mark); switch (i) { /* note that we decode until a CTI, so for every case the suffix is decoded * and changes in later cases may fail even the earlier ones. */ case 0: test_inval_0(); case 1: test_inval_1(); case 2: test_inval_2(); case 3: test_inval_3(); case 4: test_inval_4(); case 5: test_inval_5(); case 6: test_inval_6(); case 7: test_inval_7(); default: ; } print("All done\n"); #ifdef USE_DYNAMO dynamorio_app_stop(); dynamorio_app_exit(); #endif return 0; }
int main(int argc, char** argv) { #ifdef WINDOWS HMODULE hmod; /* * Cause an exception event */ __try { HANDLE heap = GetProcessHeap(); char *buf = (char *)HeapAlloc(((char *)heap)+1, HEAP_GENERATE_EXCEPTIONS, 10); } __except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { } /* * Load and unload a module to cause a module unload event */ hmod = LoadLibrary(argv[1]); if (hmod == NULL) { print("LoadLibrary failed: %x\n", GetLastError()); } FreeLibrary(hmod); #endif #ifdef LINUX void *hmod; char buf[1000]; size_t len = 0; char *end_path = NULL; /* * Load and unload a module to cause a module unload event */ /* FIXME: We used to test a module with a large .bss here. Try to do that * again. */ hmod = dlopen(argv[1], RTLD_LAZY|RTLD_LOCAL); if (hmod != NULL) dlclose(hmod); else print("module load failed: %s\n", dlerror()); /* test load of non-existent file */ hmod = dlopen("foo_bar_no_exist.so", RTLD_LAZY|RTLD_LOCAL); if (hmod != NULL) { print("ERROR - module load of %s succeeded\n", buf); dlclose(hmod); } intercept_signal(SIGUSR1, signal_handler, false); intercept_signal(SIGUSR2, signal_handler, false); intercept_signal(SIGURG, signal_handler, false); print("Sending SIGUSR1\n"); kill(getpid(), SIGUSR1); print("Sending SIGUSR2\n"); kill(getpid(), SIGUSR2); print("Sending SIGURG\n"); kill(getpid(), SIGURG); print("Done\n"); /* * Cause a fork event */ if (fork() == 0) { abort(); } else { wait(NULL); } #endif /* LINUX */ #ifdef WINDOWS /* * Cause an exception event, we test redirecting the application to redirect() */ __try { HANDLE heap = GetProcessHeap(); char *buf = (char *)HeapAlloc(((char *)heap)+1, HEAP_GENERATE_EXCEPTIONS, 10); } __except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { } #else *(int *)4 = 0; #endif /* Never Reached */ print("Shouldn't be reached\n"); }
int main() { void *p1; int x, *arr; char c; p1 = malloc(64); free(p1); printf("malloc\n"); for (x = 0; x < 20; x++) { /* ensure we flag an error if reading the padding even though it * is safe to access */ p1 = malloc(3); c = *(((char *)p1)+3); /* error: unaddressable */ free(p1); } printf("malloc small\n"); p1 = malloc(0); free(p1); printf("malloc 0\n"); p1 = malloc(512*1024); if (*(((char *)p1)+3) == 0) /* error: uninitialized */ c = 2; /* PR 488643: test realloc via mremap */ p1 = realloc(p1, 1024*1024); free(p1); printf("malloc big\n"); p1 = calloc(3, sizeof(int)); x = *((int *)p1); /* ok: initialized to 0 */ free(p1); printf("calloc\n"); p1 = malloc(64); if (*(((char *)p1)+3) == 0) /* error: uninitialized */ c = 2; p1 = realloc(p1, 128); p1 = realloc(p1, sizeof(int)*2); arr = (int *) p1; arr[0] = 1; arr[1] = 2; p1 = realloc(p1, sizeof(int)*3); arr = (int *) p1; arr[2] = 3; /* shouldn't produce unaddr */ if ((arr[0] + arr[1] + arr[2]) != 6) /* shouldn't produce uninit */ printf("realloc\n"); free(p1); arr = NULL; /* PR 416535: test realloc(NULL, ), and on some linuxes, nested * tailcall (PR 418138) */ p1 = realloc(NULL, 32); free(p1); /* PR 493870: test realloc(non-NULL, 0) */ p1 = malloc(37); p1 = realloc(p1, 0); /* get a 2nd malloc at same spot to test PR 493880 */ p1 = malloc(37); free(p1); #ifdef WINDOWS /* HeapReAlloc has different behavior: (,0) does allocate a 0-sized chunk */ p1 = HeapAlloc(GetProcessHeap(), 0, 0xab); p1 = HeapReAlloc(GetProcessHeap(), 0, p1, 0); HeapFree(GetProcessHeap(), 0, p1); #endif printf("realloc\n"); /* invalid free: crashes so we have a try/except. * glibc catches invalid free only at certain points near real mallocs. */ #ifdef UNIX intercept_signal(SIGSEGV, signal_handler); #else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) our_top_handler); #endif if (setjmp(mark) == 0) free((void *)0x1230); /* i#916: addr must be 0x10 aligned */ printf("invalid free\n"); #if 0 /* avoiding double free b/c glibc reports it and aborts */ free(p1); printf("double free\n"); #endif #ifdef WINDOWS p1 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(int)); x = *((int *)p1); /* ok: initialized to 0 */ HeapFree(GetProcessHeap(), 0, p1); p1 = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NULL, sizeof(int)); HeapFree(GetProcessHeap(), 0, p1); { /* test failure of HeapFree due to invalid params */ HANDLE newheap = HeapCreate(0, 0, 0); BOOL ok = TRUE; char save[8]; /* to recover on win7 */ p1 = HeapAlloc(newheap, HEAP_ZERO_MEMORY, sizeof(int)); memcpy(save, (char *)p1 - sizeof(save), sizeof(save)); if (setjmp(mark) == 0) { /* crashes on win7 (i#515) */ /* i#1161: we cannot recover from a heap exception on win8 */ if (is_pre_win8()) ok = HeapFree(GetProcessHeap(), 0, p1); else ok = HeapFree(newheap, 0, (void*)0x300); if (!ok) /* invalid Heap fails w/ 87 "The parameter is incorrect." */ printf("HeapFree failed %d\n", GetLastError()); } else printf("HeapFree failed 87\n"); /* match non-crash error */ /* restore so we can try to free (else crashes again on win7) */ memcpy((char *)p1 - sizeof(save), save, sizeof(save)); ok = HeapFree(newheap, 0xffffffff, p1); if (!ok) /* invalid flags do not cause failure */ printf("HeapFree failed %d\n", GetLastError()); HeapDestroy(newheap); } #endif /* Test leaks. Avoid non-determinism due to the order of drmem's hashtable walk: * for this test drmem's malloc table has 12 bits, so be sure to get the * following allocs all in order in the table by not wrapping around in the * bottom 12 bits. We assume all the allocs below take < 512 bytes. Note: this * isn't always sufficient, but .res matches out-of-order now */ { static char *p; p = malloc(8); /* static so no leak */ free(p); if (0xfff - ((int)(size_t)p & 0xfff) < 512) /* truncation ok in cast */ p = calloc(1, 0xfff - ((int)(size_t)p & 0xfff)); /* calloc for i#927 */ else p = NULL; /* prevent from pointing where p1 will be (i#340) */ } /* error: both leaked, though one points to other neither is reachable * once p1 goes out of scope, so one direct and one indirect leak */ p1 = calloc(1, 42); /* calloc for i#927 */ *((void**)p1) = malloc(17); /* not a leak: still reachable through persistent pointer p2 */ p2 = calloc(1, 8); /* calloc for i#927 */ *((void**)p2) = malloc(19); /* PR 513954: app-added size field not a leak */ p3 = calloc(1, 24); /* calloc for i#927 */ *((size_t*)p3) = 24; p3 = (void *) (((char*)p3) + 8); /* align to 8 so matches malloc alignment */ /* test PR 576032's identification of direct vs indirect leaks * = is head pointer, - is mid-chunk pointer: * * X=========== * || * V * A ==> B ==> C --> D * | \\=> E * | \-> F * ----------/ * * We expect reported: * 1) Leak pA + pB + pC + pE * 2) Possible leak pF * 3) Leak pX + pD * Note: I used to have pX=>pB to further test dup dependents, but * it's too difficult to control the ordering on all platforms. */ { char *pA, *pB, *pC, *pD, *pE, *pF, *pX; pA = malloc(sizeof(pA)*4); pB = malloc(sizeof(pB)*4); pC = malloc(sizeof(pC)*4); pD = malloc(sizeof(pD)*4); pE = malloc(sizeof(pE)*4); pF = malloc(sizeof(pF)*4); pX = malloc(sizeof(pX)*4); *((char **)pA) = pB; *((char **)pB) = pC; *((char **)(pB + sizeof(pB))) = pF + sizeof(pF); *((char **)pC) = pD + sizeof(pD); *((char **)(pC + sizeof(pC))) = pE; *((char **)(pC + 2*sizeof(pC))) = pF + sizeof(pF); *((char **)(pX + sizeof(pX))) = pD; } if (setjmp(mark) == 0) { c = *(char *)0x100; /* i#1015: unaddr on wild access */ } printf("all done\n"); return 0; }
int main() { int *pc; int release_build = 0; /* 1 == release, 0 == debug */ void *dcontext; int *dstack; int tls_offs; ptr_int_t owning_thread; INIT(); #ifdef UNIX intercept_signal(SIGSEGV, (handler_3_t) signal_handler, false); #else SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) our_top_handler); #endif #ifdef WINDOWS /* brute force loop over all TLS entries, * and see whether owning_thread is GetCurrentThreadId() * 0:001> dt getdc owning_thread * +0x05c owning_thread : 0xed8 * * 0:001> dt _TEB TLS64 * +0xe10 TLS64 : [64] Ptr32 Void */ for (tls_offs = 63; tls_offs >=0; tls_offs--) { enum {offsetof_TLS64_in_TEB = IF_X64_ELSE(0x1480, 0xe10)}; dcontext_tls_offset = offsetof_TLS64_in_TEB + tls_offs*sizeof(void*); GET_DCONTEXT(dcontext); #if VERBOSE print("%d idx, %x offs\n", tls_offs, dcontext_tls_offset); #endif where = SIGSETJMP(mark); if (where == 0) { owning_thread = *(ptr_int_t *)(((char *)dcontext) + OWNING_THREAD_OFFSET_IN_DCONTEXT); /* we didn't crash reading, is it really thread ID? */ #if VERBOSE print(" %d thread %d vs %d\n", tls_offs, owning_thread, GetCurrentThreadId()); #endif if (owning_thread == GetCurrentThreadId()) { #if VERBOSE print(" %d is dcontext!\n", tls_offs); #endif break; } } else { #if VERBOSE print(" %d crashed\n", tls_offs); #endif /* we crashed reading, try next offset */ } } if (tls_offs < 0) { print("error obtaining dcontext (TLS offset not found): " "are you running natively?!?\n"); exit(1); } #endif where = SIGSETJMP(mark); if (where != 0) { print("error obtaining dcontext (SIGSETJMP failed): " "are you running natively?!?\n"); exit(1); } GET_DCONTEXT(dcontext) #if VERBOSE print("dcontext is "PFX"\n", dcontext); #endif dstack = *(int **)(((char *)dcontext) + DSTACK_OFFSET_IN_DCONTEXT); if (dstack == NULL || !ALIGNED(dstack, PAGE_SIZE)) { print("can't find dstack: old build, or new where dstack offset changed?\n"); while (1) ; exit(-1); } dstack_base = (int *) (((char *)dstack) - DSTACK_SIZE); #if VERBOSE print("dstack is "PFX"-"PFX"\n", dstack_base, dstack); #endif print("dcontext->dstack successfully obtained\n"); where = SIGSETJMP(mark); #if VERBOSE print("SIGSETJMP returned %d\n", where); #endif if (where == 0) { /* if we do the copy in a C loop, trace heads cause us to exit before * we've hit the cxt switch return address, so we crash rather than taking * control -- so we hand-code a copy that in C looks like this: * for (pc = dstack_base; pc++; pc < dstack) * *pc = (int) evil; * we assume df is cleared * FIXME: popf in old fcache_return can trigger a trap crash before * get to ret that goes to evil! * FIXME: I had this getting to evil w/o crashing first, but it's * a little fragile, and on win32 I get issues later b/c we have * trampolines, etc. and so don't completely lose control. * But, in all cases we fail, so whether it's a nice shell code * execution or a crash doesn't matter -- the test does what it's supposed * to do! */ evil_copy(dstack_base, DSTACK_SIZE / sizeof(int), (ptr_int_t)evil); print("wrote to entire dstack without incident!\n"); } else if (where == 1) { print("error writing to "PFX" in expected dstack "PFX"-"PFX"\n", pc, dstack_base, dstack); } else if (where == 2) { print("DR has been cracked! Malicious code is now runnning...\n"); } }
int main(int argc, char *argv[]) { int rc; struct itimerval t; struct rusage ru; int arg_offs = 1; FP = stderr; /* default */ if (argc < 2) { return usage(argv[0]); } while (argv[arg_offs][0] == '-') { if (strcmp(argv[arg_offs], "-s") == 0) { if (argc <= arg_offs+1) return usage(argv[0]); limit = atoi(argv[arg_offs+1]); arg_offs += 2; } else if (strcmp(argv[arg_offs], "-m") == 0) { if (argc <= arg_offs+1) return usage(argv[0]); limit = atoi(argv[arg_offs+1])*60; arg_offs += 2; } else if (strcmp(argv[arg_offs], "-h") == 0) { if (argc <= arg_offs+1) return usage(argv[0]); limit = atoi(argv[arg_offs+1])*3600; arg_offs += 2; } else if (strcmp(argv[arg_offs], "-v") == 0) { /* just ignore -v, only here for compatibility with texec */ arg_offs += 1; } else if (strcmp(argv[arg_offs], "-silent") == 0) { silent = 1; arg_offs += 1; } else if (strcmp(argv[arg_offs], "-killpg") == 0) { kill_group = 1; arg_offs += 1; } else if (strcmp(argv[arg_offs], "-f") == 0) { char fname[32]; int len = snprintf(fname, sizeof(fname)/sizeof(fname[0]), "runstats-%d", getpid()); if (len <= 0) return 1; FP = fopen(fname, "w"); arg_offs += 1; } else if (strcmp(argv[arg_offs], "-env") == 0) { if (argc <= arg_offs+2) return usage(argv[0]); #if VERBOSE fprintf(FP, "setting env var \"%s\" to \"%s\"\n", argv[arg_offs+1], argv[arg_offs+2]); #endif rc = setenv(argv[arg_offs+1], argv[arg_offs+2], 1/*overwrite*/); if (rc != 0 || strcmp(getenv(argv[arg_offs+1]), argv[arg_offs+2]) != 0) { fprintf(FP, "error in setenv of \"%s\" to \"%s\"\n", argv[arg_offs+1], argv[arg_offs+2]); fprintf(FP, "setenv returned %d\n", rc); fprintf(FP, "env var \"%s\" is now \"%s\"\n", argv[arg_offs+1], getenv(argv[arg_offs+1])); exit(-1); } arg_offs += 3; } else { return usage(argv[0]); } if (limit < 0) { return usage(argv[0]); } if (argc - arg_offs < 1) return usage(argv[0]); } gettimeofday(&start, (struct timezone *) 0); child = fork(); if (child < 0) { perror("ERROR on fork"); return 1; } else if (child > 0) { pid_t result; int status; get_mem_stats(child); intercept_signal(SIGALRM, (handler_t) signal_handler); intercept_signal(SIGCHLD, (handler_t) signal_handler); t.it_interval.tv_sec = 0; t.it_interval.tv_usec = 500000; t.it_value.tv_sec = 0; t.it_value.tv_usec = 500000; /* must use real timer so timer decrements while process suspended */ rc = setitimer(ITIMER_REAL, &t, NULL); assert(rc == 0); #if VERBOSE fprintf(FP, "parent waiting for child\n"); #endif /* need loop since SIGALRM will interrupt us */ do { result = wait3(&status, 0, &ru); } while (result != child); gettimeofday(&end, (struct timezone *) 0); #if VERBOSE fprintf(FP, "child has exited\n"); #endif /* turn off timer */ t.it_interval.tv_usec = 0; t.it_value.tv_usec = 0; rc = setitimer(ITIMER_REAL, &t, NULL); assert(rc == 0); if (!silent) print_stats(&start, &end, &ru, status); return (status == 0 ? 0 : 1); } else { int result; if (kill_group) { /* Change the process group so we can relibably kill all children. * This assumes that no child will change the process group or * invoke sub-commands via bash. */ result = setpgid(0 /* my pid */, 0 /* set pgid to my pid */); if (result < 0) { perror("ERROR in setpgid"); fprintf(FP, " trying to run %s\n", argv[arg_offs]); return 1; } } result = execvp(argv[arg_offs], argv+arg_offs); if (result < 0) { perror("ERROR in execvp"); fprintf(FP, " trying to run %s\n", argv[arg_offs]); return 1; } } return 0; }