DF-3330 / guard.h
/* Common guard-page helper (fork-based, robust): place a buffer at the * very end of a mapped page followed by a PROT_NONE page; run the * verbatim code in a forked child -- exit(0) = ran cleanly, killed by * SIGSEGV/SIGBUS = the over-read crossed the guard page (proof). */ #ifndef GUARD_H #define GUARD_H #include <sys/mman.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <unistd.h> static char * guard_buf(size_t len) /* returns buffer of exactly len usable bytes */ { long pg = sysconf(_SC_PAGESIZE); char *base = mmap(NULL, 2 * pg, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (base == MAP_FAILED) { perror("mmap"); exit(2); } if (mprotect(base + pg, pg, PROT_NONE) < 0) { perror("mprotect"); exit(2); } return base + pg - len; /* end of the FIRST page; second page is the guard */ } static const char *gu_desc; static int gu_quiet; static int gu_check(void (*fn)(void), const char *desc) { pid_t pid; int st; gu_desc = desc; fflush(stdout); pid = fork(); if (pid == 0) { fn(); _exit(0); } waitpid(pid, &st, 0); if (WIFSIGNALED(st) && (WTERMSIG(st) == SIGSEGV || WTERMSIG(st) == SIGBUS)) { printf(" SEGV in child -- %s\n", gu_desc); return (1); } if (!gu_quiet) printf(" (child ran without fault)\n"); return (0); } #endif |