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; }
static void test_sandbox_fault(void) { int i; print("start fault test\n"); protect_mem(sandbox_fault_no_ilt, 1024, ALLOW_READ|ALLOW_WRITE|ALLOW_EXEC); i = SIGSETJMP(mark); if (i == 0) sandbox_fault(42); /* i#1441: test max writes with illegal instr */ protect_mem(sandbox_illegal_no_ilt, 1024, ALLOW_READ|ALLOW_WRITE|ALLOW_EXEC); i = SIGSETJMP(mark); if (i == 0) sandbox_illegal_instr(42); print("end fault test\n"); }
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 invalid_ret(int x) { ptr_int_t bad_retaddr = x; /* Sign extend x on X64. */ where = SIGSETJMP(mark); if (where == 0) { call_with_retaddr((void *)ring, bad_retaddr); print("unexpectedly we came back!"); } else { print("fault caught on " PFX "\n", x); } return 0; }
int R_SelectEx(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout, void (*intr)(void)) { if (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0) /* Is it right for select calls with a timeout to be non-interruptable? LT */ return select(n, readfds, writefds, exceptfds, timeout); else { volatile sel_intr_handler_t myintr = intr != NULL ? intr : onintr; volatile int old_interrupts_suspended = R_interrupts_suspended; if (SIGSETJMP(seljmpbuf, 1)) { myintr(); R_interrupts_suspended = old_interrupts_suspended; error(_("interrupt handler must not return")); return 0; /* not reached */ } else { int val; /* make sure interrupts are enabled -- this will be restored if there is a LONGJMP from myintr() to another context. */ R_interrupts_suspended = FALSE; /* install a temporary signal handler for breaking out of a blocking select */ oldSigintHandler = signal(SIGINT, handleSelectInterrupt); /* once the new sinal handler is in place we need to check for and handle any pending interrupt registered by the standard handler. */ if (R_interrupts_pending) myintr(); /* now do the (possibly blocking) select, restore the signal handler, and return the result of the select. */ val = select(n, readfds, writefds, exceptfds, timeout); signal(SIGINT, oldSigintHandler); R_interrupts_suspended = old_interrupts_suspended; return val; } } }
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; }
/* * fvwmSelect - wrapper around the select() system call. * This system call may block indefinitely. We don't want * to block at all if the "terminate" flag is set - we * just want it to fail as quickly as possible. */ int fvwmSelect(fd_set_size_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { volatile int iRet = -1; /* This variable MUST NOT be in a register */ #ifdef C_ALLOCA /* If we're using the C version of alloca, see if anything needs to be * freed up. */ alloca(0); #endif /* * Yes, we trash errno here, but you're only supposed to check * errno immediately after a function fails anyway. If we fail, * then it's because we received a signal. If we succeed, we * shouldn't be checking errno. And if somebody calls us expecting * us to preserve errno then that's their bug. * * NOTE: We mustn't call any function that might trash errno * ourselves, except select() itself of course. I believe * that sigsetjmp() does NOT trash errno. */ errno = EINTR; /* * Now initialise the non-local jump. Between here and the end of * the routine (more-or-less) we must NOT call any non-reentrant * functions! This is because we might need to abandon them half * way through execution and return here! */ if ( SIGSETJMP(deadJump, 1) == SIG_INIT ) { /* * Activate the non-local jump. Between now and when we turn the * jump off again, we must NOT call any non-reentrant functions * because we could be interrupted halfway through ... */ canJump = true; /* * If we have already been told to terminate then we will not * execute the select() because the flag will be set. If a * "terminate" signal arrives between testing the flag and * calling select() then we will jump back to the non-local * jump point ... */ if ( !isTerminated ) { /* * The "die" signal will interrupt this system call: * that IS the whole point, after all :-) */ iRet = select(nfds, SELECT_FD_SET_CAST readfds, SELECT_FD_SET_CAST writefds, SELECT_FD_SET_CAST exceptfds, timeout); } /* * The non-local jump is about to go out of scope, * so we must deactivate it. Note that the return- * value from select() will be safely stored in the * local variable before the jump is disabled. */ canJump = false; } return iRet; }
int my_setjmp(sigjmp_buf env) { return SIGSETJMP(env); }
int main(int argc, char *argv[]) { double res = 0.; int i; # ifndef X64 int j; # endif char *buf; # ifdef UNIX stack_t sigstack; # endif # ifdef UNIX /* 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, (handler_3_t)signal_handler, true); intercept_signal(SIGSEGV, (handler_3_t)signal_handler, true); # 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(UNIX) || 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 = SIGSETJMP(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 = SIGSETJMP(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 = SIGSETJMP(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 = SIGSETJMP(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(); # ifdef WINDOWS /* FIXME i#105: crashing on Linux so disabling for now */ /* PR 242815: data16 mbr */ print("Testing data16 mbr\n"); test_data16_mbr(); # endif /* i#1024: rip-rel ind branch */ print("Testing rip-rel ind branch\n"); func_ptr = actual_call_target; test_rip_rel_ind(); /* i#1118: subtle prefix opcode issues */ test_bsr(); i = SIGSETJMP(mark); if (i == 0) { test_SSE2(); } /* i#1493: segment register mangling */ test_mangle_seg(); # ifdef UNIX free(sigstack.ss_sp); # endif print("All done\n"); return 0; }
int main(int argc, char *argv[]) { double res = 0.; int i; #ifdef UNIX intercept_signal(SIGILL, (handler_3_t) signal_handler, false); intercept_signal(SIGSEGV, (handler_3_t) signal_handler, false); #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 = SIGSETJMP(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 (SIGSETJMP(mark) == 0) { test_prefix_1(); } invalid_lock = false; print("Invalid instructions about to happen\n"); count = 0; i = SIGSETJMP(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"); 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"); } }