DF-3567 / guard_bf_len0.c
/* * guard_bf_len0.c - prove BF_set_key dereferences data[0] when len == 0 * (sys/crypto/blowfish/bf_skey.c:83-99). * * A zero-length key buffer has no readable bytes; we model it by placing * `data` at a PROT_NONE guard page. The first of the 72 key-schedule byte * reads (ri = *(d++)) faults; si_addr == data proves the dereference. * Exit 42 = fault confirmed at data[0]. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <sys/mman.h> #include <sys/types.h> #include <crypto/blowfish/blowfish.h> static void handler(int sig, siginfo_t *si, void *uc) { (void)uc; printf("FAULT-CONFIRMED: sig=%d si_addr=%p (expected data[0] at guard page)\n", sig, si->si_addr); fflush(stdout); _exit(42); } int main(void) { BF_KEY key; unsigned char *guard; struct sigaction sa; guard = mmap(NULL, 2 * 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); if (guard == MAP_FAILED || mprotect(guard + 4096, 4096, PROT_NONE) != 0) { perror("mmap/mprotect"); return 2; } memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = handler; sa.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &sa, NULL); sigaction(SIGBUS, &sa, NULL); printf("calling BF_set_key(&key, len=0, data=guard-page %p)\n", (void *)(guard + 4096)); fflush(stdout); BF_set_key(&key, 0, guard + 4096); /* data[0] dereference -> fault */ printf("BUG-NOT-PRESENT: survived len=0\n"); return 0; } |