DragonFlyBSD Kernel Audit
DF-0785 / harness_fixed.c
← back to finding ↓ download raw
/* DF-0785 harness WITH the proposed fix: kmalloc(max(blsize,rdsize)).
 * Identical to harness.c except the poisoned allocation sizes the buffer to
 * max(blsize,rdsize) -- so the rdsize-byte memcpy fits and no overflow occurs.
 * Build: cc -O2 -o harness_fixed harness_fixed.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>
static long PAGE=0;
static unsigned char *poison_alloc(uint32_t n){
    char *base=mmap(NULL,PAGE*2,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
    if(base==MAP_FAILED){perror("mmap");exit(2);}
    if(mprotect(base+PAGE,PAGE,PROT_NONE)!=0){perror("mprotect");exit(2);}
    return (unsigned char*)(base+PAGE-n);
}
int main(int argc,char**argv){
    PAGE=sysconf(_SC_PAGESIZE);
    uint32_t blsize=(argc>1)?(uint32_t)strtoul(argv[1],0,0):16;
    uint32_t rdsize=(argc>2)?(uint32_t)strtoul(argv[2],0,0):200;
    uint32_t allocsz = (blsize<rdsize)?rdsize:blsize;   /* <-- THE FIX */
    printf("[harness-fixed] blsize=%u rdsize=%u  -> kmalloc(max)=%u\n",blsize,rdsize,allocsz);
    unsigned char *attacker=malloc(rdsize); memset(attacker,0x44,rdsize);
    unsigned char *rdbuf=poison_alloc(allocsz);
    printf("[harness-fixed] rdbuf=%p (last %u bytes of page; next page PROT_NONE)\n",(void*)rdbuf,allocsz);
    printf("[harness-fixed] performing memcpy of %u bytes (fits in %u-byte buffer)...\n",rdsize,allocsz);
    fflush(stdout);
    memcpy(rdbuf,attacker,rdsize);   /* no overflow: allocsz>=rdsize */
    printf("[harness-fixed] memcpy completed cleanly -- NO OVERFLOW (fix effective)\n");
    return 0;
}