#include #include #include #include #define BINDSTACK_SIZE 0x1000000 #define BINDSTACK_PAGE_SIZE 0x1000 #define BINDSTACK_LOW_GUARD_PAGE 0x0ffe000 #define BINDSTACK_HIGH_GUARD_PAGE 0xfff000 void *bindstack; struct symdata { unsigned int pad0; unsigned int value; unsigned int pad2; unsigned int pad3; unsigned int pad4; unsigned int pad5; }; #define SYMDATA_SIZE 0x6000 /* 1024 entries, 6 words/entry, 4 bytes/word */ struct symdata *symdata; int trap_1_hit; void protect_low(int protect) { mprotect(bindstack + BINDSTACK_LOW_GUARD_PAGE, BINDSTACK_PAGE_SIZE, protect? 0: PROT_READ | PROT_WRITE | PROT_EXEC); } void protect_high(int protect) { mprotect(bindstack + BINDSTACK_HIGH_GUARD_PAGE, BINDSTACK_PAGE_SIZE, protect? 0: PROT_READ | PROT_WRITE | PROT_EXEC); } void sigsegv_handler(int signal, siginfo_t *info, void *context) { void *addr = info->si_addr; if (addr == (bindstack + BINDSTACK_HIGH_GUARD_PAGE)) { printf("trap 1\n"); protect_high(0); protect_low(1); trap_1_hit = 1; } else if ((addr > (bindstack + BINDSTACK_LOW_GUARD_PAGE)) && (addr < (bindstack + BINDSTACK_HIGH_GUARD_PAGE))) { printf("trap 2\n"); protect_high(1); protect_low(0); } else { printf("unknown trap address %p\n", addr); abort(); } } void run_bind_test(void) { unsigned int *p = bindstack; unsigned int i = 0; while (!trap_1_hit) { p[0] = (unsigned int)&symdata[i]; p[1] = symdata[i].value; symdata[i].value = 0xf001f001; p += 2; i = (i + 1) & 1023; } while (p != bindstack) { p -= 2; ((struct symdata *)p[0])->value = p[1]; p[0] = 0; p[1] = 0; } } int main(void) { struct sigaction sa; if (sigprocmask(SIG_BLOCK, NULL, &sa.sa_mask)) { perror("sigprocmask"); return 0; } sa.sa_sigaction = sigsegv_handler; sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_RESTART; if (sigaction(SIGSEGV, &sa, NULL)) { perror("sigaction"); return 0; } bindstack = mmap(NULL, BINDSTACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (bindstack == MAP_FAILED) { perror("mmap bindstack"); return 0; } symdata = mmap(NULL, SYMDATA_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (symdata == MAP_FAILED) { perror("mmap symdata"); return 0; } protect_high(1); trap_1_hit = 0; printf("bindstack: %p, symdata: %p\n", bindstack, symdata); run_bind_test(); printf("done\n"); return 0; }