DF-5694 / aslr_probe.c
/* End-to-end PoC: mmap base randomization distribution on the live * DragonFly kernel. vm_map_hint() (sys/vm/vm_map.c:4408) computes * addr = vm_daddr + dsiz + (karc4random64() & 0x7fff..) % dsiz * with default dsiz = 32GB. The karc4random64 sign-extension bug * puts 9/16 of placements in the TOP 4GB of that span. * This program needs no privileges and no kernel modules. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> int main(void) { unsigned long long bucket[8] = {0}; unsigned long long lo = ~0ULL, hi = 0, n = 0; int N = 100000; for (int i = 0; i < N; i++) { void *p = mmap(NULL, 4096, PROT_READ, MAP_ANON, -1, 0); if (p == MAP_FAILED) { perror("mmap"); return 1; } unsigned long long a = (unsigned long long)p; if (a < lo) lo = a; if (a > hi) hi = a; munmap(p, 4096); n++; } unsigned long long base = lo & ~0x7fffffffULL; /* page-align span start approx */ /* bucket by 4GB relative to observed low address */ for (int i = 0; i < N; i++) { void *p = mmap(NULL, 4096, PROT_READ, MAP_ANON, -1, 0); if (p == MAP_FAILED) break; unsigned long long rel = (unsigned long long)p - lo; unsigned long long b = rel >> 32; if (b < 8) bucket[b]++; munmap(p, 4096); } printf("n=%llu lo=0x%llx hi=0x%llx span_top4GB_frac=", n, lo, hi); double top = (double)bucket[7] / (double)(n); printf("%.4f (uniform: 0.1250, bug predicts 0.5625)\n", top); for (int i = 0; i < 8; i++) printf(" bucket[%d]: %llu (%.4f)\n", i, bucket[i], (double)bucket[i] / (double)n); return 0; } |