/* 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;
}
