/* * ------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42 - bzerk) * wrote this file. As long as you retain this notice * you can do whatever you want with this stuff. If we meet some day, * and you think this stuff is worth it, you can buy me a beer in * return. Ruben de Groot * ------------------------------------------------------------------- */ /* jailinit.c, RdG 2002 */ static const char copyright[] = "Copyright (c) 2002 Ruben de Groot, BZERK.ORG.\n"; #if !defined(__FreeBSD__) || __FreeBSD__ < 4 #error This program only works on FreeBSD >= 4.x #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define UP_SCRIPT "/etc/rc" #define DOWN_SCRIPT "/etc/rc.shutdown" #define SHELL_PATH "/bin/sh" #define SHELL "sh" #define JIPID "/var/run/jailinit.pid" #define MAX_LINE 255 FILE *jf; void script_exec(shell, args) char *shell; char *args[]; { pid_t pid; if ((pid = fork()) == 0) execv(shell, args); else waitpid(pid, NULL, 0); } void kill_procs(sig) int sig; { kvm_t *kd; struct kinfo_proc *pbase; struct kinfo_proc *pp; int nproc, i; kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open"); pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc); for (pp = pbase, i = 0; i < nproc; pp++, i++) #if __FreeBSD__ == 4 if (((pp)->kp_proc.p_stat) != 0 && ((pp)->kp_proc.p_pid) != getpid() && ((pp)->kp_proc.p_pid) >1) kill(((pp)->kp_proc.p_pid), sig); #endif #if __FreeBSD__ >= 5 if ((pp->ki_stat != 0) && (pp->ki_pid != getpid()) && (pp->ki_pid >1)) kill(pp->ki_pid, sig); #endif } void jailrc(sig) int sig; { char *args[3]; struct stat sb; signal(SIGTERM, SIG_IGN); signal(SIGHUP, SIG_IGN); if (stat(DOWN_SCRIPT, &sb) == 0) { args[0] = SHELL; args[1] = DOWN_SCRIPT; args[2] = 0; logwtmp("~", "shutdown", ""); script_exec(SHELL_PATH, args); } kill_procs(SIGTERM); sleep(2); kill_procs(SIGKILL); if ((stat(UP_SCRIPT, &sb) == 0) && (sig == SIGHUP)) { args[0] = SHELL; args[1] = UP_SCRIPT; args[2] = 0; logwtmp("~", "reboot", ""); script_exec(SHELL_PATH, args); if ((jf = fopen(JIPID, "w")) != NULL) fprintf(jf, "%d\n", getpid()); else exit(2); fclose(jf); } else { logwtmp("~", "halt", ""); unlink(JIPID); exit(sig); } signal(SIGTERM, jailrc); signal(SIGHUP, jailrc); } int check_if_jailed(void) { kvm_t *kd; struct kinfo_proc *pbase; struct kinfo_proc *pp; int nproc, i; kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open"); pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc); for (pp = pbase, i = 0; i < nproc; pp++, i++) #if __FreeBSD__ == 4 if (((pp)->kp_proc.p_stat) != 0 && ((pp)->kp_proc.p_pid) == getpid() ) return (int) ((pp)->kp_proc.p_prison); #endif #if __FreeBSD__ >= 5 if ((pp->ki_stat != 0) && (pp->ki_pid == getpid() )) return ( pp->ki_flag & P_JAILED ); #endif /* something must be terribly wrong, so we'll assume we're not in jail */ return 0; } int main(argc, argv) int argc; char *argv[]; { char *args[3]; int s; if (! check_if_jailed()) { printf("We are not in a jail!\nexiting...\n"); exit(1); } for (s = 1; s < NSIG; s++) signal(s, SIG_IGN); signal(SIGTERM, jailrc); signal(SIGHUP, jailrc); daemon(0,0); args[0] = SHELL; args[1] = UP_SCRIPT; args[2] = 0; logwtmp("~", "boot", ""); script_exec(SHELL_PATH, args); if ((jf = fopen(JIPID, "w")) != NULL) fprintf(jf, "%d\n", getpid()); else exit(2); fclose(jf); while (1) { pause(); } }