#include #include #include #include #include #include #include #include "extremesandbox.h" #include "int64.h" #define EMPTYDIRECTORY "/var/chroot/extremesandbox" #define BASEUID 141500000 #define MAXPID 1000000000 #ifndef RLIMIT_NOFILE #define RLIMIT_NOFILE RLIMIT_OFILE #endif /* uids between BASEUID and BASEUID+MAXPID-1 * must not be used by anything else */ int extremesandbox(void) { struct rlimit r; int64 targetuid; int64 pid; int childstatus; /* prohibit new files, new sockets, etc. */ if (getrlimit(RLIMIT_NOFILE,&r) == -1) return -1; r.rlim_cur = 0; r.rlim_max = 0; if (setrlimit(RLIMIT_NOFILE,&r) == -1) return -1; /* allow testing by non-root users */ if (geteuid() != 0) return 0; /* prohibit access to filesystem */ if (chdir(EMPTYDIRECTORY) == -1) return -1; if (chroot(EMPTYDIRECTORY) == -1) return -1; pid = getpid(); if (pid < 0) return -1; if (pid >= 1000000000) return -1; targetuid = 141500000 + pid; /* double-check that uid isn't hanging around */ switch(pid = fork()) { case -1: return -1; case 0: setuid(targetuid); kill(-1,SIGKILL); _exit(0); } while (waitpid(pid,&childstatus,0) != pid) ; if (!WIFEXITED(childstatus)) return -1; /* prohibit kill, ptrace, etc. */ if (setgid(targetuid) == -1) return -1; if (setuid(targetuid) == -1) return -1; if (getgid() != targetuid) return -1; if (getuid() != targetuid) return -1; /* prohibit fork */ if (getrlimit(RLIMIT_NPROC,&r) == -1) return -1; r.rlim_cur = 0; r.rlim_max = 0; if (setrlimit(RLIMIT_NPROC,&r) == -1) return -1; return 0; }