diff options
author | Stef Walter <stef@memberwebs.com> | 2004-05-18 16:23:45 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2004-05-18 16:23:45 +0000 |
commit | 4bef00e8f39ef127ff8922d0931e7ffd95950d20 (patch) | |
tree | b8f4a5387c0619fae659f43ea330a6b0ef75140c | |
parent | 887d8b57c4aa291919c8eec6b2af5a5f5259ac6d (diff) |
Tested on FreeBSD 5.2.1. Fixed bugs.
-rw-r--r-- | ChangeLog | 0 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | config.h.in | 6 | ||||
-rw-r--r-- | configure.ac | 29 | ||||
-rw-r--r-- | src/Makefile | 21 | ||||
-rw-r--r-- | srcx/jails.c | 13 | ||||
-rw-r--r-- | srcx/jid.c | 49 | ||||
-rw-r--r-- | srcx/jkill.c | 117 | ||||
-rw-r--r-- | srcx/jps.c | 34 | ||||
-rw-r--r-- | srcx/jstart.c | 30 | ||||
-rw-r--r-- | srcx/util.c | 233 | ||||
-rw-r--r-- | srcx/util.h | 20 |
12 files changed, 354 insertions, 202 deletions
diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ChangeLog diff --git a/Makefile.am b/Makefile.am index 0739508..f107da2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,5 @@ + +SUBDIRS = $(SRC_SUB) EXTRA_DIST = BUGS -SUBDIRS = src +DIST_SUBDIRS = src srcx diff --git a/config.h.in b/config.h.in index f528c73..f7ce6f4 100644 --- a/config.h.in +++ b/config.h.in @@ -6,6 +6,9 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the `c' library (-lc). */ +#undef HAVE_LIBC + /* Define to 1 if you have the `kvm' library (-lkvm). */ #undef HAVE_LIBKVM @@ -87,6 +90,9 @@ /* Version number of package */ #undef VERSION +/* In debug mode */ +#undef _DEBUG + /* Define to empty if `const' does not conform to ANSI C. */ #undef const diff --git a/configure.ac b/configure.ac index 3b34e62..be33655 100644 --- a/configure.ac +++ b/configure.ac @@ -8,13 +8,31 @@ AM_CONFIG_HEADER([config.h]) # Checks for programs. AC_PROG_CC +# Debug mode +AC_ARG_ENABLE(debug, + AC_HELP_STRING([--enable-debug], + [Compile binaries in debug mode])) + +if test "$enable_debug" = "yes"; then + CFLAGS="$CFLAGS -g -O0" + AC_DEFINE_UNQUOTED(_DEBUG, 1, [In debug mode]) + echo "enabling debug compile mode" +fi + # Checks for libraries. -AC_CHECK_LIB([kvm], [kvm_open]) +AC_CHECK_LIB([kvm], [kvm_open], , + [ echo "ERROR: Must have FreeBSD 4.x or higher"; exit 1]) # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([syslog.h path.h fcntl.h limits.h sys/param.h]) +# Check for jail stuff and figure out jail capabilities +AC_CHECK_LIB([c], [jail], , + [ echo "ERROR: Must have jail capabilities (FreeBSD 4.x or higher)"; exit 1]) +AC_CHECK_LIB([c], [jail_attach], + [ JAIL_ATTACH=yes; ], ) + # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T @@ -28,6 +46,13 @@ AC_FUNC_MALLOC AC_STRUCT_TM -AC_CONFIG_FILES([Makefile src/Makefile]) +if test "$JAIL_ATTACH" = "yes"; then + SRC_SUB=srcx +else + SRC_SUB=src +fi + +AC_SUBST([SRC_SUB]) +AC_CONFIG_FILES([Makefile src/Makefile srcx/Makefile]) AC_OUTPUT diff --git a/src/Makefile b/src/Makefile index 7b914d5..f5739c5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,7 +13,7 @@ -SHELL = /bin/sh +SHELL = /usr/local/bin/bash srcdir = . top_srcdir = .. @@ -38,10 +38,10 @@ pkglibdir = $(libdir)/jailutils pkgincludedir = $(includedir)/jailutils top_builddir = .. -ACLOCAL = ${SHELL} /usr/work/src/jailutils/missing --run aclocal -AUTOCONF = ${SHELL} /usr/work/src/jailutils/missing --run autoconf -AUTOMAKE = ${SHELL} /usr/work/src/jailutils/missing --run automake -AUTOHEADER = ${SHELL} /usr/work/src/jailutils/missing --run autoheader +ACLOCAL = ${SHELL} /home/nate/jail-work/jailutils/missing --run aclocal +AUTOCONF = ${SHELL} /home/nate/jail-work/jailutils/missing --run autoconf +AUTOMAKE = ${SHELL} /home/nate/jail-work/jailutils/missing --run automake +AUTOHEADER = ${SHELL} /home/nate/jail-work/jailutils/missing --run autoheader INSTALL = /usr/bin/install -c INSTALL_PROGRAM = ${INSTALL} @@ -55,7 +55,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -AMTAR = ${SHELL} /usr/work/src/jailutils/missing --run tar +AMTAR = ${SHELL} /home/nate/jail-work/jailutils/missing --run tar AWK = nawk CC = gcc DEPDIR = .deps @@ -63,10 +63,11 @@ EXEEXT = INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s OBJEXT = o PACKAGE = jailutils +SRC_SUB = srcx VERSION = 0.5.4 am__include = include am__quote = -install_sh = /usr/work/src/jailutils/install-sh +install_sh = /home/nate/jail-work/jailutils/install-sh sbin_PROGRAMS = killjail jails killjail_SOURCES = killjail.c getjail.c getjail.h @@ -95,7 +96,7 @@ DEFS = -DHAVE_CONFIG_H DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = LDFLAGS = -LIBS = -lkvm +LIBS = -lc -lkvm depcomp = $(SHELL) $(top_srcdir)/depcomp DEP_FILES = $(DEPDIR)/getjail.Po $(DEPDIR)/jails.Po \ $(DEPDIR)/killjail.Po @@ -103,7 +104,7 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -CFLAGS = -g -O2 +CFLAGS = -g -O2 -g -O0 DIST_SOURCES = $(jails_SOURCES) $(killjail_SOURCES) NROFF = nroff @@ -176,7 +177,7 @@ distclean-depend: depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \ $(CCDEPMODE) $(depcomp) \ $(COMPILE) -c `cygpath -w $<` -CCDEPMODE = depmode=gcc +CCDEPMODE = depmode=gcc3 uninstall-info-am: man8dir = $(mandir)/man8 diff --git a/srcx/jails.c b/srcx/jails.c index aac6a31..ed6b353 100644 --- a/srcx/jails.c +++ b/srcx/jails.c @@ -1,10 +1,15 @@ #include <sys/types.h> +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/sysctl.h> + #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <kvm.h> #include <paths.h> +#include <errno.h> #include "util.h" @@ -20,7 +25,7 @@ int main(int argc, char* argv[]) if(argc > 1) usage(); - if(in_jail()) + if(running_in_jail()) errx(1, "can't run from inside jail"); list_jails(); @@ -67,11 +72,11 @@ retry: if(len < sizeof(*xp) || len % sizeof(*xp) || xp->pr_version != XPRISON_VERSION) errx(1, "kernel and userland out of sync"); - jid = -1; - for(i = 0; i < (len / sizeof(*xp)); i++) - printf("%s\n", xp->pr_host); + printf("%s\n", xp[i].pr_host); free(sxp); } + + @@ -1,5 +1,8 @@ #include <sys/types.h> +#include <sys/param.h> +#include <sys/jail.h> + #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -14,8 +17,8 @@ static void usage(); int main(int argc, char* argv[]) { - int i; int jid = 0; + char* e; /* Remove the program name */ argc--; @@ -24,14 +27,47 @@ int main(int argc, char* argv[]) if(argc != 1) usage(); - if(in_jail()) + if(running_in_jail()) errx(1, "can't run from inside jail"); - jid = translate_jail_id(argv[0]); - if(jid == -1) - errx(1, "unknown jail host name: %s", argv[0]); + jid = strtol(argv[0], &e, 10); + + /* If it was all a number ... */ + if(!*e) + { + struct xprison* xp; + size_t len, i; + + len = get_jail_sysctl(&xp); + if(len > 0) + { + for(i = 0; i < len; i++) + { + if(xp[i].pr_id == jid) + { + printf("%s\n", xp[i].pr_host); + jid = -1; + break; + } + } + + free(xp); + + if(jid != -1) + errx(1, "unknown jail id: %s", argv[0]); + } + } + + /* otherwise it's a host name */ + else + { + jid = translate_jail_name(argv[0]); + if(jid == -1) + errx(1, "unknown jail host name: %s", argv[0]); + + printf("%d\n", (int)jid); + } - printf("%d \n", (int)jid); return 0; } @@ -40,3 +76,4 @@ static void usage() fprintf(stderr, "usage: jid hostname \n"); exit(2); } + diff --git a/srcx/jkill.c b/srcx/jkill.c index 46b1815..fd3c110 100644 --- a/srcx/jkill.c +++ b/srcx/jkill.c @@ -1,9 +1,11 @@ + #include <sys/types.h> #include <sys/stat.h> #include <sys/param.h> #include <sys/sysctl.h> #include <sys/proc.h> #include <sys/user.h> +#include <sys/wait.h> #include <paths.h> #include <signal.h> @@ -29,6 +31,12 @@ int g_timeout = DEFAULT_TIMEOUT; /* Supress warnings */ int g_quiet = 0; +int g_verbose = 0; + +static void kill_jail_processes(kvm_t* kd, int sig); +static int kill_jail(const char* jail, int restart, int force); +static int check_running_processes(kvm_t* kd); +static void usage(); int main(int argc, char* argv[]) { @@ -36,9 +44,10 @@ int main(int argc, char* argv[]) int ret = 0; int restart = 0; int force = 0; + int verbose = 0; pid_t child; - while((ch = getopt(argc, argv, "fhqrt:")) != -1) + while((ch = getopt(argc, argv, "fhqrt:v")) != -1) { switch(ch) { @@ -46,15 +55,16 @@ int main(int argc, char* argv[]) force = 1; break; - case 'q': - g_quiet = 1; - break; - case 'h': /* dummy for compatibility with killjail */ warnx("the '-h' option has been depreciated"); break; + case 'q': + g_quiet = 1; + g_verbose = 0; + break; + case 'r': restart = 1; break; @@ -66,6 +76,11 @@ int main(int argc, char* argv[]) errx(2, "invalid timeout argument: %s", optarg); break; + case 'v': + g_verbose = 1; + g_quiet = 0; + break; + case '?': default: usage(); @@ -79,13 +94,16 @@ int main(int argc, char* argv[]) if(argc == 0) usage(); + if(running_in_jail()) + errx(1, "can't run inside jail"); + /* For each jail */ - while(argc > 0) + for(; argc > 0; argc--, argv++) { - jid = translate_jail(argv[0]); + jid = translate_jail_name(argv[0]); if(jid == -1) { - warnx(1, "unknown jail host name: %s", argv[0]); + warnx("unknown jail host name: %s", argv[0]); ret = 1; continue; } @@ -94,7 +112,7 @@ int main(int argc, char* argv[]) * We fork and the child goes into the jail and * does the dirty work. */ - +#ifdef _DEBUG switch((child = fork())) { /* Error condition */ @@ -104,22 +122,25 @@ int main(int argc, char* argv[]) /* The child */ case 0: +#endif if(jail_attach(jid) == -1) err(1, "couldn't attach to jail"); - r = kill_jail(restart, force, argv[0]); + r = kill_jail(argv[0], restart, force); exit(r); +#ifdef _DEBUG break; /* The parent */ default: - if(waitpid(child, &r, options) == -1) + if(waitpid(child, &r, 0) == -1) err(1, "error waiting for child process"); - if(r != 0) - ret = r; + if(WEXITSTATUS(r) != 0) + ret = WEXITSTATUS(r); break; }; +#endif argc--; argv++; @@ -128,13 +149,20 @@ int main(int argc, char* argv[]) return ret; } -int kill_jail(int restart, int force, const char* name) +#define SHUTDOWN_SCRIPT "/etc/rc.shutdown" +static char* SHUTDOWN_ARGS[] = { _PATH_BSHELL, SHUTDOWN_SCRIPT }; + +#define START_SCRIPT "/etc/rc" +static char* START_ARGS[] = { _PATH_BSHELL, START_SCRIPT }; + +static int kill_jail(const char* jail, int restart, int force) { kvm_t* kd = NULL; char errbuf[_POSIX2_LINE_MAX]; int pass = 0; int timeout = 0; int ret = 0; + int cmdargs = JAIL_RUN_CONSOLE; /* Open the kernel interface */ kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, _PATH_DEVNULL, @@ -142,11 +170,14 @@ int kill_jail(int restart, int force, const char* name) if(kd == NULL) errx(1, "couldn't connect to kernel: %s", errbuf); + if(g_verbose) + cmdargs |= JAIL_RUN_STDERR; + /* * Multiple passes are used to do different things. * Each time the jails processes are listed. */ - while(true) + while(1) { while(timeout > 0) { @@ -163,8 +194,8 @@ int kill_jail(int restart, int force, const char* name) case 0: /* Check if we have an executable shutdown script */ - if(check_jail_command(name, "/etc/rc.shutdown")) - run_jail_command(name, "/etc/rc.shutdown", NULL, JAIL_OUT_CONSOLE); + if(check_jail_command(jail, SHUTDOWN_SCRIPT)) + run_jail_command(jail, SHUTDOWN_ARGS[0], SHUTDOWN_ARGS, cmdargs); break; @@ -174,14 +205,20 @@ int kill_jail(int restart, int force, const char* name) timeout = g_timeout; break; - /* Okay now we force kill the processes if necessary */ + /* ... and again ... */ case 2: + kill_jail_processes(kd, SIGTERM); + timeout = g_timeout; + break; + + /* Okay now we force kill the processes if necessary */ + case 3: if(force) { /* If we get here, jailer looks like it's really irresponsive */ if(!g_quiet) - warnx("%s: jail won't stop. forcing jail termination...", name); + warnx("%s: jail won't stop. forcing jail termination...", jail); kill_jail_processes(kd, SIGKILL); timeout = g_timeout; @@ -189,27 +226,14 @@ int kill_jail(int restart, int force, const char* name) break; + case 4: - case 3: - - if(check_running_processes(kd)) - { - /* And if that didn't do it, well then give up */ - if(!g_quiet) - warnx("%s: couldn't stop jail, processes wouldn't die", name); - - ret = 1; - goto done; - } - - else if(restart) - { - /* Check if we have an executable shutdown script */ - if(check_jail_command(name, "/etc/rc")) - run_jail_command(name, "/etc/rc", NULL, JAIL_OUT_CONSOLE); + /* And if that didn't do it, well then give up */ + if(!g_quiet) + warnx("%s: couldn't stop jail, processes wouldn't die", jail); - goto done; - } + ret = 1; + goto done; } pass++; @@ -219,13 +243,20 @@ int kill_jail(int restart, int force, const char* name) } done: + if(restart) + { + /* Check if we have an executable shutdown script */ + if(check_jail_command(jail, START_SCRIPT)) + run_jail_command(jail, START_ARGS[0], START_ARGS, cmdargs); + } + if(kd != NULL) kvm_close(kd); return ret; } -void kill_jail_processes(kvm_t* kd, int sig) +static void kill_jail_processes(kvm_t* kd, int sig) { struct kinfo_proc* kp; int nentries, i; @@ -251,7 +282,7 @@ void kill_jail_processes(kvm_t* kd, int sig) } } -int check_running_processes(kvm_t* kd) +static int check_running_processes(kvm_t* kd) { struct kinfo_proc* kp; int nentries, i; @@ -263,7 +294,7 @@ int check_running_processes(kvm_t* kd) if((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nentries)) == 0) errx(1, "couldn't list processes: %s", kvm_geterr(kd)); - if(&nentries != 1) + if(nentries != 1) return 1; /* Okay now loop and look at each process' jail */ @@ -278,6 +309,8 @@ int check_running_processes(kvm_t* kd) static void usage() { - fprintf(stderr, "usage: killjail [ -r ] [ -t timeout ] [ -qf ] jailname ...\n"); + fprintf(stderr, "usage: killjail [-fqrv] [-t timeout] jailname ...\n"); exit(2); } + + @@ -1,11 +1,16 @@ #include <sys/types.h> +#include <sys/param.h> +#include <sys/sysctl.h> +#include <sys/user.h> + #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <kvm.h> #include <paths.h> +#include <limits.h> #include "util.h" @@ -14,8 +19,8 @@ #endif static void usage(); -static void printJailIds(); -static void runJailPs(int argc, char* argv[]); +static void print_jail_ids(); +static void run_jail_ps(int argc, char* argv[]); int main(int argc, char* argv[]) { @@ -23,11 +28,11 @@ int main(int argc, char* argv[]) int simple = 0; int jid = 0; - while((ch = getopt(argc, argv, "x")) != -1) + while((ch = getopt(argc, argv, "i")) != -1) { switch(ch) { - case 'x': + case 'i': simple = 1; break; @@ -48,7 +53,6 @@ int main(int argc, char* argv[]) errx(1, "can't run from inside jail"); /* Translate the jail name into an id if neccessary */ - name = argv[0]; jid = translate_jail_name(argv[0]); if(jid == -1) errx(1, "unknown jail host name: %s", argv[0]); @@ -79,13 +83,13 @@ int main(int argc, char* argv[]) static void usage() { - fprintf(stderr, "usage: jps [-x] jail [ ps_options ... ]\n"); + fprintf(stderr, "usage: jps [-i] jail [ ps_options ... ]\n"); exit(2); } static void run_jail_ps(int argc, char* argv[]) { - char* args[]; + char** args; int i; if(!check_jail_command(NULL, "/bin/ps")) @@ -97,7 +101,7 @@ static void run_jail_ps(int argc, char* argv[]) * then it could have replaced /bin/ps which we run... */ - args = alloca(sizeof(char*) * (argc + 2)); + args = (char**)alloca(sizeof(char*) * (argc + 2)); args[0] = "ps"; for(i = 0; i < argc; i++) @@ -105,18 +109,18 @@ static void run_jail_ps(int argc, char* argv[]) args[i + 1] = NULL; - run_jail_command(NULL, "/bin/ps", args, 0); + run_jail_command(NULL, "/bin/ps", args, JAIL_RUN_NOFORK); } static void print_jail_ids() { kvm_t* kd; + int nentries, i; struct kinfo_proc* kp; char errbuf[_POSIX2_LINE_MAX]; /* Open kernel interface */ - kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, _PATH_DEVNULL, - O_RDONLY, errbuf); + kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf); if(kd == NULL) errx(1, "couldn't connect to kernel: %s", errbuf); @@ -125,8 +129,12 @@ static void print_jail_ids() errx(1, "couldn't list processes: %s", kvm_geterr(kd)); for(i = 0; i < nentries; i++) - printf("%d ", (int)(kp[i].ki_pid)); + { + if(kp[i].ki_pid != getpid()) + printf("%d ", (int)(kp[i].ki_pid)); + } - fputc(stdout, '\n'); + fputc('\n', stdout); kvm_close(kd); } + diff --git a/srcx/jstart.c b/srcx/jstart.c index 76bdaae..370c064 100644 --- a/srcx/jstart.c +++ b/srcx/jstart.c @@ -3,23 +3,17 @@ /* TODO: Attribute properly */ #include <sys/types.h> -#include <sys/stat.h> #include <sys/param.h> -#include <sys/sysctl.h> -#include <sys/proc.h> -#include <sys/user.h> +#include <sys/jail.h> + +#include <netinet/in.h> +#include <arpa/inet.h> #include <paths.h> -#include <signal.h> #include <stdio.h> -#include <syslog.h> #include <err.h> -#include <errno.h> -#include <stdarg.h> #include <unistd.h> -#include <kvm.h> #include <limits.h> -#include <fcntl.h> #include "util.h" @@ -27,9 +21,13 @@ #include "../config.h" #endif +#define START_SCRIPT "/etc/rc" +static char* START_ARGS[] = { _PATH_BSHELL, START_SCRIPT }; + +static void usage(); + int main(int argc, char* argv[]) { -#include <signal.h> int ch, jid; struct jail j; int printjid = 0; @@ -66,13 +64,12 @@ int main(int argc, char* argv[]) if(chdir(argv[0]) != 0) err(1, "couldn't change to jail directory: %s", argv[0]); - if(inet_aton(argv[2], &in) != 0) + if(inet_aton(argv[2], &in) != 1) errx(1, "invalid ip address: %s", argv[2]); memset(&j, 0, sizeof(j)); j.version = 0; j.path = argv[0]; -#include <signal.h> j.hostname = argv[1]; j.ip_number = ntohl(in.s_addr); @@ -84,7 +81,6 @@ int main(int argc, char* argv[]) if(console) { - } if(printjid) @@ -93,10 +89,10 @@ int main(int argc, char* argv[]) fflush(stdout); } - if(!check_jail_command("/etc/rc")) + if(!check_jail_command(NULL, START_SCRIPT)) exit(1); - run_jail_command("/etc/rc"); + run_jail_command(NULL, START_ARGS[0], START_ARGS, JAIL_RUN_CONSOLE | JAIL_RUN_STDOUT); return 0; } @@ -105,3 +101,5 @@ static void usage() fprintf(stderr, "usage: jstart [-ic] path hostname ip-number\n"); exit(2); } + + diff --git a/srcx/util.c b/srcx/util.c index 6c1d811..8591292 100644 --- a/srcx/util.c +++ b/srcx/util.c @@ -1,11 +1,13 @@ #include <sys/types.h> -#include <sys/user.h> -#include <sys/proc.h> #include <sys/param.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/stat.h> #include <sys/jail.h> #include <sys/sysctl.h> #include <sys/file.h> +#include <sys/wait.h> #include <err.h> #include <errno.h> @@ -16,26 +18,15 @@ #include <kvm.h> #include <paths.h> -int translate_jail_name(const char* str) -{ - struct xprison* sxp; - struct xprison* xp; - size_t len, i; - char* e; - int jid; +#include "util.h" - jid = strtol(str, &e, 10); +extern char** environ; - /* If it was all a number ... */ - if(!*e) - { - if(jid > 0) - return jid; - - errx(1, "invalid jail id: %s", str); - } - - /* ... otherwise it's a name */ +size_t get_jail_sysctl(struct xprison** ret) +{ + struct xprison* xp; + size_t len; + *ret = NULL; if(sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1) err(1, "couldn't list jails"); @@ -43,17 +34,17 @@ int translate_jail_name(const char* str) retry: if(len <= 0) - return -1; + return 0; - sxp = xp = calloc(len, 1); - if(sxp == NULL) + xp = calloc(len, 1); + if(xp == NULL) err(1, "out of memory"); if(sysctlbyname("security.jail.list", xp, &len, NULL, 0) == -1) { if(errno == ENOMEM) { - free(sxp); + free(xp); goto retry; } @@ -63,19 +54,55 @@ retry: if(len < sizeof(*xp) || len % sizeof(*xp) || xp->pr_version != XPRISON_VERSION) errx(1, "kernel and userland out of sync"); + *ret = xp; + return len / sizeof(*xp); +} + +int translate_jail_name(const char* str) +{ + struct xprison* xp = NULL; + size_t len, i; + char* e; + int jid; + + len = get_jail_sysctl(&xp); + if(len == 0) + goto done; + + jid = strtol(str, &e, 10); + + /* If it was all a number ... */ + if(!*e) + { + if(jid <= 0) + errx(1, "invalid jail id: %s", str); + + /* Validate the number */ + for(i = 0; i < len; i++) + { + if(jid == xp[i].pr_id) + goto done; + } + + jid = -1; + } + jid = -1; - for(i = 0; i < (len / sizeof(*xp)); i++) + for(i = 0; i < len; i++) { - if(strcmp(xp->pr_host, str) == 0) + if(strcmp(xp[i].pr_host, str) == 0) { - jid = xp->pr_id; + jid = xp[i].pr_id; break; } } - free(sxp); - return -1; +done: + if(xp) + free(xp); + + return jid; } /* @@ -93,8 +120,7 @@ int running_in_jail() char errbuf[_POSIX2_LINE_MAX]; int result = -1; - kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, _PATH_DEVNULL, - O_RDONLY, errbuf); + kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); if(kd == NULL) errx(1, "couldn't connect to kernel: %s", errbuf); @@ -115,46 +141,56 @@ int check_jail_command(const char* jail, const char* cmd) if(stat(cmd, &sb) == -1) { - if(errno == EACCESS || errno == ELOOP || errno == ENAMETOOLONG || + if(errno == EACCES || errno == ELOOP || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR) { - warn("%s%scan't execute in jail: %s", , jail ? jail : "", - jail ? jail : ": ", cmd); + warn("%s%scan't execute in jail: %s", jail ? jail : "", + jail ? ": " : "", cmd); return 0; } - err(1, "%s%scouldn't stat file: %s", , jail ? jail : "", - jail ? jail : ": ", cmd); + err(1, "%s%scouldn't stat file: %s", jail ? jail : "", + jail ? ": " : "", cmd); } if(!(sb.st_mode & S_IFREG)) { - warnx("%s%snot a regular file: %s", , jail ? jail : "", - jail ? jail : ": ", cmd); - return 0; - } - - if(!(sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - { - warnx("%s%snot executable: %s", , jail ? jail : "", - jail ? jail : ": ", cmd); + warnx("%s%snot a regular file: %s", jail ? jail : "", + jail ? ": " : "", cmd); return 0; } if(sb.st_uid != 0) { warnx("%s%snot owned by root: %s", jail ? jail : "", - jail ? jail : ": ", cmd); + jail ? ": " : "", cmd); return 0; } return 1; } -int run_simple_command(const char* jail, const char* cmd, char* args[]) +int run_overlay_command(const char* jail, const char* cmd, char* env[], + char* args[]) +{ + if(args) + execve(cmd, args, env); + else + execle(cmd, cmd, NULL, env); + + warn("%s%serror executing: %s: %s", jail ? jail : "", + jail ? ": " : "", cmd); + return 0; +} + +int run_simple_command(const char* jail, const char* cmd, char* env[], + char* args[], int opts) { pid_t pid; - int status; + int status = 0; + + if(opts & JAIL_RUN_NOFORK) + return run_overlay_command(jail, cmd, env, args); switch((pid = fork())) { @@ -165,7 +201,7 @@ int run_simple_command(const char* jail, const char* cmd, char* args[]) /* This is the child here */ case 0: if(args) - exect(cmd, args, env); + execve(cmd, args, env); else execle(cmd, cmd, NULL, env); @@ -176,14 +212,14 @@ int run_simple_command(const char* jail, const char* cmd, char* args[]) default: /* If the processes exited then break out */ - if(waitpid(pid, &status, 0) == pid) - break; + if(waitpid(pid, &status, 0) == -1) + err(1, "couldn't wait on child process"); /* Return any status codes */ - if(status != 0) + if(WEXITSTATUS(status) != 0) { warnx("%s%serror executing: %s: %s", jail ? jail : "", - jail ? jail : ": ", cmd, strerror(status)); + jail ? ": " : "", cmd, strerror(WEXITSTATUS(status))); return 0; } @@ -193,7 +229,17 @@ int run_simple_command(const char* jail, const char* cmd, char* args[]) return 1; } -int run_dup_command(const char* jail, const char* cmd, char* argv[] args, int opts) +/* read & write ends of a pipe */ +#define READ_END 0 +#define WRITE_END 1 + +/* pre-set file descriptors */ +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 + +int run_dup_command(const char* jail, const char* cmd, char* env[], + char* args[], int opts) { int outpipe[2]; pid_t pid; @@ -228,7 +274,7 @@ int run_dup_command(const char* jail, const char* cmd, char* argv[] args, int op /* Okay, now run whatever command it was */ if(args) - exect(cmd, args, env); + execve(cmd, args, env); else execle(cmd, cmd, NULL, env); @@ -250,12 +296,13 @@ int run_dup_command(const char* jail, const char* cmd, char* argv[] args, int op int ret; int status = 0; fd_set readmask; + char buff[256]; struct timeval timeout = { 0, 10000 }; FD_ZERO(&readmask); /* Open the console file and write the header */ - if(opts & JAIL_OUT_CONSOLE) + if(opts & JAIL_RUN_CONSOLE) console = open(_PATH_CONSOLE, O_WRONLY | O_APPEND); /* No blocking on the child processes pipe */ @@ -274,10 +321,10 @@ int run_dup_command(const char* jail, const char* cmd, char* argv[] args, int op /* Read text */ while((ret = read(outpipe[READ_END], buff, 256)) > 0) { - if(opts & JAIL_OUT_STDOUT) + if(opts & JAIL_RUN_STDOUT) write(STDOUT, buff, ret); - if(opts & JAIL_OUT_STDERR) + if(opts & JAIL_RUN_STDERR) write(STDERR, buff, ret); if(console != -1) @@ -295,10 +342,10 @@ int run_dup_command(const char* jail, const char* cmd, char* argv[] args, int op } /* Return any status codes */ - if(status != 0) + if(WEXITSTATUS(status) != 0) { warnx("%s%serror executing: %s: %s", jail ? jail : "", - jail ? jail : ": ", cmd, strerror(status)); + jail ? ": " : "", cmd, strerror(WEXITSTATUS(status))); return 0; } @@ -314,53 +361,41 @@ int run_dup_command(const char* jail, const char* cmd, char* argv[] args, int op return 1; } -#define MAKE_ENV_VAR(v, n) \ -{ \ - char* t = getenv(n); \ - t = t ? t : ""; \ - (v) = alloca(strlen(n) + 2 + strlen(t)); \ - sprintf((v), "%s=%s", (n), (v)); \ -} - -/* read & write ends of a pipe */ -#define READ_END 0 -#define WRITE_END 1 - -/* pre-set file descriptors */ -#define STDIN 0 -#define STDOUT 1 -#define STDERR 2 int run_jail_command(const char* jail, const char* cmd, char* args[], int opts) { char* env[5]; + char* t; + int j; + char** x; + + memset(env, 0, sizeof(env)); + +#define MAKE_ENV_VAR(n) \ + t = getenv(n); \ + if(t != NULL) \ + { \ + env[j] = alloca(strlen(n) + 2 + strlen(t)); \ + sprintf(env[j], "%s=%s", (char*)(n), t); \ + j++; \ + } /* Prepare an environment for the cmd */ env[0] = "PATH=" _PATH_STDPATH; - env[1] = NULL; + j = 1; - /* - * If we're outputing to the console then we need a - * few more environement variables. Processes like - * 'ps' depend on them for formatting. - */ - if(!opts || opts & JAIL_OUT_STDOUT || - opts & JAIL_OUT_STDERR) - { - /* TODO: For fun debugging. Remove later */ - t = getenv(VAR); - t = t ? t : NULL; - env[1] = alloca(sizeof("TERM") + 2 + strlen(t)); - sprintf(env[1], "%s=%s", "TERM", t); - - MAKE_ENV_VAR(env[1], "TERM"); - MAKE_ENV_VAR(env[2], "COLUMNS"); - MAKE_ENV_VAR(env[3], "LINES"); - env[4] = NULL; - } + MAKE_ENV_VAR("TERM"); + MAKE_ENV_VAR("COLUMNS"); + MAKE_ENV_VAR("LINES"); - if(opts) - return run_dup_command(jail, cmd, args, opts); + if(opts & JAIL_RUN_OUTPUT) + return run_dup_command(jail, cmd, env, args, opts); else - return run_simple_command(jail, cmd, args); + return run_simple_command(jail, cmd, env, args, opts); } + + + + + + diff --git a/srcx/util.h b/srcx/util.h index 1ac02c5..0054f15 100644 --- a/srcx/util.h +++ b/srcx/util.h @@ -1,19 +1,21 @@ #ifndef __UTIL_H__ #define __UTIL_H__ +struct xprison; + int translate_jail_name(const char* str); +size_t get_jail_sysctl(struct xprison** ret); int running_in_jail(); -/* Output stuff to the jail console if available */ -#define JAIL_OUT_CONSOLE 1 << 1 +#define JAIL_RUN_CONSOLE 0x00000001 /* Output stuff to the jail console if available */ +#define JAIL_RUN_STDOUT 0x00000002 /* Output to stdout */ +#define JAIL_RUN_STDERR 0x00000004 /* Output to stderr */ +#define JAIL_RUN_OUTPUT 0x0000000F /* All the output types */ -/* Output to stdout */ -#define JAIL_OUT_STDOUT 1 << 2 +#define JAIL_RUN_NOFORK 0x00000010 /* Don't fork, overlay current process */ -/* Output to stderr */ -#define JAIL_OUT_STDERR 1 << 3 +int run_jail_command(const char* jail, const char* cmd, char* args[], int opts); +int check_jail_command(const char* jail, const char* cmd); -int run_jail_command(const char* jail, const char* script, int opts); -int check_jail_command(const char* jail, const char* script); +#endif /* __UTIL_H__ */ -#endif __UTIL_H__ |