DF-5679 / fixdemo.c
/* * DF-5679 fix validation demo. * * Compiles against EITHER the pristine icrc32.c (baseline) or a copy * patched by fix.diff (size_t length end-to-end). It forks; the child * calls iscsi_crc32(p, 0x100000009ULL) where p has exactly 9 valid * bytes ending at a PROT_NONE guard page. * * baseline (truncating): child reads only 9 bytes, returns silently * -> "FIX-BAD" / exit 1 * patched (size_t): child honors 4 GiB + 9, faults on the guard * -> "FIX-OK" / exit 0 * * Build: cc -O2 -o fixdemo fixdemo.c <icrc32-object-under-test> * (link with icrc32.c directly; crc32.c not needed). */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <unistd.h> #include <sys/mman.h> #include <sys/wait.h> #include <signal.h> uint32_t iscsi_crc32(const void *buf, size_t size); int main(void) { size_t ps = (size_t)sysconf(_SC_PAGESIZE); unsigned char *map = mmap(NULL, 2 * ps, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); if (map == MAP_FAILED) { perror("mmap"); return (2); } mprotect(map + ps, ps, PROT_NONE); memset(map, 0xAB, ps); pid_t pid = fork(); if (pid == 0) { uint32_t v = iscsi_crc32(map + ps - 9, 0x100000009ULL); printf("child: silently returned %08x after \"4GiB+9\" " "request (length was truncated)\n", v); _exit(0); } int st = 0; waitpid(pid, &st, 0); if (WIFSIGNALED(st) && (WTERMSIG(st) == SIGSEGV || WTERMSIG(st) == SIGBUS)) { printf("FIX-OK: length honored -> child faulted on guard " "page (sig %d)\n", WTERMSIG(st)); return (0); } printf("FIX-BAD: no fault (status 0x%x); truncation still " "present\n", st); return (1); } |