summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog0
-rw-r--r--Makefile.am4
-rw-r--r--config.h.in6
-rw-r--r--configure.ac29
-rw-r--r--src/Makefile21
-rw-r--r--srcx/jails.c13
-rw-r--r--srcx/jid.c49
-rw-r--r--srcx/jkill.c117
-rw-r--r--srcx/jps.c34
-rw-r--r--srcx/jstart.c30
-rw-r--r--srcx/util.c233
-rw-r--r--srcx/util.h20
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);
}
+
+
diff --git a/srcx/jid.c b/srcx/jid.c
index a201822..9f48b8b 100644
--- a/srcx/jid.c
+++ b/srcx/jid.c
@@ -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);
}
+
+
diff --git a/srcx/jps.c b/srcx/jps.c
index e9a6ec8..d35daab 100644
--- a/srcx/jps.c
+++ b/srcx/jps.c
@@ -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__