From ccbaa3e1b09afae32e5ec9c5a6e4325a8e5b5c6a Mon Sep 17 00:00:00 2001 From: Matt Mullins Date: Sat, 21 Sep 2013 22:59:41 +0000 Subject: [PATCH] Handle a SIGSEGV by having the main loop load from a dummy This is by far the dirtiest signal handler I've ever written. I can't believe glibc gives me access to the registers so darn easily. --- mmap_everything.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/mmap_everything.c b/mmap_everything.c index d2db52d..13d343d 100644 --- a/mmap_everything.c +++ b/mmap_everything.c @@ -1,6 +1,10 @@ +#define _GNU_SOURCE foo + #include +#include #include #include +#include #include #include #include @@ -9,6 +13,25 @@ #define MAX_BITS (sizeof(size_t) * CHAR_BIT - 1) +int dummy = 13; +int *pi; + +static void catch_sigsegv(int signal, siginfo_t *info, void *p) { + (void)(signal); + + ucontext_t *uctx = (ucontext_t*)p; + greg_t rip = uctx->uc_mcontext.gregs[REG_RIP]; + + fprintf(stderr, "Caught a segfault at %p\n", info->si_addr); + fflush(stderr); + + // Point it at a variable we can always load + pi = &dummy; + // Roll back %rip so we can reload *pi before dereferencing + rip -= 7; // length of mov 0x2006b4(%rip),%rax # 0x6012b0 + uctx->uc_mcontext.gregs[REG_RIP] = rip; +} + int main() { pid_t pid = getpid(); printf("My pid is: %d\n", pid); @@ -44,10 +67,18 @@ int main() { } } + sigset_t empty; + sigemptyset(&empty); + struct sigaction sigsegv_action = { + .sa_sigaction = catch_sigsegv, + .sa_mask = empty, + .sa_flags = SA_SIGINFO + }; + sigaction(SIGSEGV, &sigsegv_action, NULL); + srand48(time(NULL)); int data; do { - int *pi; uint32_t lower = lrand48(); uint32_t upper = lrand48(); @@ -59,10 +90,14 @@ int main() { printf("*%p = ", (void*)pi); fflush(stdout); data = *pi; - printf("%x\n", data); + if (pi != &dummy) { + printf("%04x\n", data); + } else { + printf("dummy\n"); + } if (munmap((void*)(pvalue & ~0xFFFL), 4096)) { perror("munmap"); } - } while (data == 0); + } while (data == 0 || pi == &dummy); } -- 2.11.0