/* stack guard gap testing - 2017/06/17 - w.tarreau */ #include #include #include #include #include #include #include #include #include #include static volatile void *stack_h, *stack_l, *stack_last; static volatile void *heap_h, *heap_l, *heap_last; static volatile void *anon_h, *anon_l, *anon_last; char buf[256]; int len; void dump() { printf("stack=%p [%p-%p] (%lu total bytes)\n", stack_last, stack_l, stack_h, (long)(stack_h-stack_l)); printf("heap~=%p [%p-%p] (%lu total bytes)\n", heap_last, heap_l, heap_h, (long)(heap_h-heap_l)); printf("anon~=%p [%p-%p] (%lu total bytes)\n", anon_last, anon_l, anon_h, (long)(anon_h-anon_l)); printf("heap...stack=%lu bytes\n", (long)(stack_h - heap_l)); printf("heap+anon+stack=%lu bytes\n", (long)(stack_h-stack_l+heap_h-heap_l+anon_h-anon_l)); close(0); open("/proc/self/maps", O_RDONLY); while ((len = read(0, buf, sizeof(buf))) > 0) write(1, buf, len); close(0); } void segv(int sig, siginfo_t *si, void *uc) { printf("SEGV caught\n"); dump(); exit(1); } main(int argc, char **argv) { void *p; int round; long step = -65536; stack_t ss; struct sigaction sa; if (argc > 1) step = atol(argv[1]); ss.ss_flags = 0; ss.ss_size = SIGSTKSZ; ss.ss_sp = malloc(ss.ss_size); sigaltstack(&ss, NULL); sa.sa_handler = NULL; sa.sa_sigaction = segv; sa.sa_flags = SA_ONESHOT | SA_ONSTACK; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, NULL); stack_h = NULL; round = 0; while (1) { if (step > 0) { p = mmap(0, step, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (p == MAP_FAILED) break; anon_last = p; if (!anon_l || p < anon_l) anon_l = p; if (!anon_h || p > anon_h) anon_h = p; } else { /* use sbrk() nor malloc to ensure libc doesn't use mmap() under us */ p = sbrk(0); if (sbrk(-step) == (void *)-1) { /* continue with mmap() */ step = -step; continue; //break; } heap_last = p; if (!heap_l || p < heap_l) heap_l = p; if (!heap_h || p > heap_h) heap_h = p; } round++; getchar(); p = alloca(abs(step)); stack_last = p; *(char *)p = 0; //memset(p, 0, step); if (!stack_l || p < stack_l) stack_l = p; if (!stack_h || p > stack_h) stack_h = p; } printf("mmap() failed\n"); dump(); printf("rounds: %d\n", round); }