#include #include #include #include #include #include #include #include #include #include #define PAGE_SIZE sysconf(_SC_PAGESIZE) #define PAGE_MASK (~(PAGE_SIZE-1)) #define GAP (20UL<<20) #define SIGNAL_STACK_SIZE (1UL<<20) #define MAPING_PROT PROT_NONE void recurse(void) { void * ptr = alloca(10); recurse(); } #define MAPPED_LEN PAGE_SIZE static unsigned long mapped_addr; void segv_handler(int sig, siginfo_t *info, void *data) { unsigned long addr = (unsigned long)info->si_addr; unsigned long mmap_end = mapped_addr + MAPPED_LEN; unsigned long diff; char cmd[128]; #ifndef CONFIG_STACK_GROWSUP diff = addr - mmap_end; #else diff = mmap_addr - addr; #endif printf("address:0x%lx aligned:0x%lx mapped:[%lx,%lx] diff:%ld\n", addr, addr & PAGE_MASK, mapped_addr, mapped_addr+PAGE_SIZE, (long)diff); snprintf(cmd, sizeof(cmd) - 1, "cat /proc/%d/smaps | grep -A5 -B21 -A20 '\\[stack\\]'", getpid()); system(cmd); abort(); } int main(int argc, char **argv) { void *addr; stack_t signal_stack; struct sigaction segv_sig = {.sa_sigaction = segv_handler, .sa_flags = SA_ONSTACK|SA_SIGINFO}; int stack_top; unsigned long mmap_gap = GAP; struct rlimit rlim = {.rlim_cur = 2*GAP, .rlim_max = RLIM_INFINITY}; unsigned long stack_addr = (unsigned long)&stack_top; if (argc > 1) { char *endptr; mmap_gap = strtoul(argv[1], &endptr, 0); if (*endptr) { fprintf(stderr, "Unrecognized mmap gap %s\n", argv[1]); return 1; } } #ifndef CONFIG_STACK_GROWSUP mapped_addr = stack_addr-mmap_gap; #else mapped_addr = stack_addr+mmap_gap; #endif mapped_addr &= PAGE_MASK; addr = mmap((void *)mapped_addr, MAPPED_LEN, MAPING_PROT, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0); if (addr == MAP_FAILED) { perror("mmap:"); return 1; } printf("Stack top:0x%lx mmap:0x%lx\n", stack_addr, mapped_addr); /* Make sure that our SEGV handler will have a stack to run on */ signal_stack.ss_sp = malloc(SIGNAL_STACK_SIZE); if (!signal_stack.ss_sp) { perror("alternate stack allocation"); return 1; } signal_stack.ss_size = SIGNAL_STACK_SIZE; signal_stack.ss_flags = 0; if (sigaltstack(&signal_stack, NULL) == -1) { perror("sigaltstack"); return 1; } sigaction(SIGSEGV, &segv_sig, NULL); sigaction(SIGBUS, &segv_sig, NULL); setrlimit(RLIMIT_STACK, &rlim); recurse(); /* Should never return */ return 1; }