DragonFlyBSD Kernel Audit
DF-0053 / mkjail.c
← back to finding ↓ download raw
/* mkjail - create a jail with N IPv4 IPs via jail(2) directly (bypasses jail(8)'s
 * ~24-IP realloc limit).  Run as root.  Usage: mkjail <path> <hostname> <n_ips> <sleeper> */
#include <sys/types.h>
#include <sys/syscall.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* Match struct jail ABI from sys/sys/jail.h (the syscall arg struct). */
struct jail_abi {
    uint32_t version;
    char *path;
    char *hostname;
    uint32_t n_ips;
    struct sockaddr_storage *ips;
};

int main(int argc, char **argv){
    if(argc < 5){ fprintf(stderr,"usage: %s path host n_ips sleeper\n",argv[0]); return 1; }
    const char *path=argv[1], *host=argv[2];
    int n=atoi(argv[3]); const char *sleeper=argv[4];
    struct sockaddr_storage *ips = calloc(n, sizeof(struct sockaddr_storage));
    for(int i=0;i<n;i++){
        struct sockaddr_in *s4=(struct sockaddr_in*)&ips[i];
        s4->sin_family=AF_INET;
        unsigned a=10,b=0,c=(i/256),d=(i%254)+1;
        s4->sin_addr.s_addr=htonl((a<<24)|(b<<16)|(c<<8)|d);
    }
    struct jail_abi j; memset(&j,0,sizeof(j));
    j.version=1; j.path=(char*)path; j.hostname=(char*)host; j.n_ips=n; j.ips=ips;
    pid_t pid=fork();
    if(pid==0){
        long _jr=syscall(SYS_jail,&j); if(_jr<0){ perror("jail"); _exit(1); }
        chdir("/");
        char *av[2]={(char*)sleeper,NULL}; char *ev[1]={NULL};
        execve(sleeper,av,ev);
        for(;;) pause();
    }
    sleep(2);
    printf("mkjail: pid=%d n_ips=%d host_len=%zu\n",pid,n,strlen(host));
    return 0;
}