summaryrefslogtreecommitdiff
path: root/srcx
diff options
context:
space:
mode:
Diffstat (limited to 'srcx')
-rw-r--r--srcx/jails.c35
-rw-r--r--srcx/jid.c8
-rw-r--r--srcx/jkill.c10
-rw-r--r--srcx/jps.c8
-rw-r--r--srcx/jstart.c78
-rw-r--r--srcx/util.c211
-rw-r--r--srcx/util.h13
7 files changed, 231 insertions, 132 deletions
diff --git a/srcx/jails.c b/srcx/jails.c
index 0394a35..40b12a7 100644
--- a/srcx/jails.c
+++ b/srcx/jails.c
@@ -77,40 +77,15 @@ static void usage()
static void list_jails()
{
- struct xprison* sxp;
struct xprison* xp;
size_t len, i;
+ jails jls;
/* ... otherwise it's a name */
+ jails_load(&jls);
- if(sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1)
- err(1, "couldn't list jails");
+ while((xp = jails_next(&jls)) != NULL)
+ printf("%s\n", xp->pr_host);
-retry:
-
- if(len <= 0)
- return;
-
- sxp = xp = calloc(len, 1);
- if(sxp == NULL)
- err(1, "out of memory");
-
- if(sysctlbyname("security.jail.list", xp, &len, NULL, 0) == -1)
- {
- if(errno == ENOMEM)
- {
- free(sxp);
- goto retry;
- }
-
- err(1, "couldn't list jails");
- }
-
- if(len < sizeof(*xp) || len % sizeof(*xp) || xp->pr_version != XPRISON_VERSION)
- errx(1, "kernel and userland out of sync");
-
- for(i = 0; i < (len / sizeof(*xp)); i++)
- printf("%s\n", xp[i].pr_host);
-
- free(sxp);
+ jails_done(&jls);
}
diff --git a/srcx/jid.c b/srcx/jid.c
index f441ad6..a637eec 100644
--- a/srcx/jid.c
+++ b/srcx/jid.c
@@ -54,9 +54,9 @@ static void usage();
int main(int argc, char* argv[])
{
- struct xprison* sxp = NULL;
struct xprison* xp = NULL;
size_t len;
+ jails jls;
char* e;
/* Remove the program name */
@@ -69,8 +69,8 @@ int main(int argc, char* argv[])
if(running_in_jail() != 0)
errx(1, "can't run from inside jail");
- len = get_jail_sysctl(&sxp);
- xp = find_jail(argv[0], len, sxp);
+ jails_load(&jls);
+ xp = jails_find(&jls, argv[0]);
strtol(argv[0], &e, 10);
@@ -92,6 +92,8 @@ int main(int argc, char* argv[])
printf("%d\n", xp->pr_id);
}
+ jails_done(&jls);
+
return 0;
}
diff --git a/srcx/jkill.c b/srcx/jkill.c
index 1d5fa0e..aa7f9b8 100644
--- a/srcx/jkill.c
+++ b/srcx/jkill.c
@@ -88,8 +88,8 @@ static void usage_hr(const char* name);
int main(int argc, char* argv[])
{
- struct xprison* sxp = NULL;
struct xprison* xp = NULL;
+ jails jls;
size_t len;
int jid, r, ret = 0;
pid_t child;
@@ -128,12 +128,12 @@ int main(int argc, char* argv[])
argc -= optind;
argv += optind;
- len = get_jail_sysctl(&sxp);
+ jails_load(&jls);
/* For each jail */
for(; argc > 0; argc--, argv++)
{
- xp = find_jail(argv[0], len, sxp);
+ xp = jails_find(&jls, argv[0]);
if(xp == NULL)
{
@@ -164,7 +164,7 @@ int main(int argc, char* argv[])
jid = xp->pr_id;
/* Always free jail info before going into jail */
- free_jail_sysctl(len, sxp);
+ jails_done(&jls);
if(jail_attach(jid) == -1)
err(1, "couldn't attach to jail");
@@ -189,7 +189,7 @@ int main(int argc, char* argv[])
argv++;
}
- free_jail_sysctl(len, sxp);
+ jails_done(&jls);
return ret;
}
}
diff --git a/srcx/jps.c b/srcx/jps.c
index 2a59c69..3340726 100644
--- a/srcx/jps.c
+++ b/srcx/jps.c
@@ -62,8 +62,8 @@ static void run_jail_ps(int argc, char* argv[]);
int main(int argc, char* argv[])
{
- struct xprison* sxp = NULL;
struct xprison* xp = NULL;
+ jails jls;
size_t len;
int jid, ch = 0;
int simple = 0;
@@ -93,8 +93,8 @@ int main(int argc, char* argv[])
errx(1, "can't run from inside jail");
/* Translate the jail name into an id if neccessary */
- len = get_jail_sysctl(&sxp);
- xp = find_jail(argv[0], len, sxp);
+ jails_load(&jls);
+ xp = jails_find(&jls, argv[0]);
if(xp == NULL)
errx(1, "unknown jail host name: %s", argv[0]);
@@ -108,7 +108,7 @@ int main(int argc, char* argv[])
jid = xp->pr_id;
/* Always free jail info before going into jail */
- free_jail_sysctl(len, sxp);
+ jails_done(&jls);
/* Go into the jail */
if(jail_attach(jid) == -1)
diff --git a/srcx/jstart.c b/srcx/jstart.c
index 6360f06..c61f484 100644
--- a/srcx/jstart.c
+++ b/srcx/jstart.c
@@ -44,12 +44,15 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/jail.h>
+#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <netdb.h>
#include <paths.h>
#include <stdio.h>
+#include <stdlib.h>
#include <err.h>
#include <unistd.h>
#include <limits.h>
@@ -66,7 +69,8 @@ static char* START_ARGS[] = { _PATH_BSHELL, START_SCRIPT, NULL };
static void usage();
-#ifdef JAIL_MULTIPATCH
+/* Jail structure with multi address patch */
+#if defined(JAIL_MULTIPATCH)
static void allocate_address(char* arg, struct jail* j)
{
@@ -101,7 +105,77 @@ static void free_address(struct jail* j)
free(j->ips);
}
-#else /* !JAIL_MULTIPATCH */
+/* Jail structure with multi address (FreeBSD 7.2+) */
+#elif defined(JAIL_MULTIADDR)
+
+static void add_addresses(struct jail *j, struct addrinfo *all)
+{
+ struct addrinfo *res;
+ void *mem;
+
+ for(res = all; res; res = res->ai_next)
+ {
+ switch(res->ai_family)
+ {
+ case AF_INET:
+ j->ip4 = realloc(j->ip4, sizeof (*(j->ip4)) * (j->ip4s + 1));
+ if(j->ip4 == NULL)
+ errx(1, "out of memory");
+ memcpy(j->ip4 + j->ip4s, &((struct sockaddr_in*)res->ai_addr)->sin_addr, sizeof (*(j->ip4)));
+ ++j->ip4s;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ j->ip6 = realloc(j->ip6, sizeof (*(j->ip6)) * (j->ip6s + 1));
+ if(j->ip6 == NULL)
+ errx(1, "out of memory");
+ memcpy(j->ip6 + j->ip6s, &((struct sockaddr_in6*)res->ai_addr)->sin6_addr, sizeof (*(j->ip6)));
+ ++j->ip6s;
+ break;
+#endif /* INET6 */
+ default:
+ errx(1, "Address family %d not supported", res->ai_family);
+ }
+ }
+}
+
+static void allocate_address(char* arg, struct jail* j)
+{
+ struct addrinfo hints, *res;
+ struct in_addr in;
+ char *ip;
+ int error, i = 0;
+
+ j->ip4s = j->ip6s = 0;
+ j->ip4 = NULL;
+ j->ip6 = NULL;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ for(i = 0, ip = strtok(arg, ","); ip; i++, ip = strtok(NULL, ","))
+ {
+ error = getaddrinfo(ip, NULL, &hints, &res);
+ if(error != 0)
+ errx(1, "invalid ip address: %s", ip);
+ add_addresses(j, res);
+ freeaddrinfo(res);
+ }
+
+ j->version = JAIL_API_VERSION;
+}
+
+static void free_address(struct jail* j)
+{
+ free(j->ip4);
+ free(j->ip6);
+}
+
+/* No jail multi addrs */
+#else
static void allocate_address(char* arg, struct jail* j)
{
diff --git a/srcx/util.c b/srcx/util.c
index 8894c61..ffea8ff 100644
--- a/srcx/util.c
+++ b/srcx/util.c
@@ -57,112 +57,155 @@
#include <string.h>
#include <unistd.h>
+#include <netinet/in.h>
+
#include "util.h"
extern char** environ;
-size_t get_jail_sysctl(struct xprison** ret)
+void
+jails_load (jails *jls)
{
- struct xprison* xp;
- size_t len;
- *ret = NULL;
-
- if(sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1)
- err(1, "couldn't list jails");
-
-retry:
+ struct xprison *xp;
- if(len <= 0)
- return 0;
-
- 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(xp);
- goto retry;
- }
+ memset (jls, 0, sizeof (jails));
- err(1, "couldn't list jails");
- }
+ if(sysctlbyname("security.jail.list", NULL, &jls->length, NULL, 0) == -1)
+ err(1, "couldn't list jails");
- if(len < sizeof(*xp) || len % sizeof(*xp) || xp->pr_version != XPRISON_VERSION)
- errx(1, "kernel and userland out of sync");
+retry:
- *ret = xp;
- return len / sizeof(*xp);
+ if(jls->length <= 0)
+ {
+ jls->data = NULL;
+ jls->last = NULL;
+ }
+
+ jls->data = calloc(jls->length, 1);
+ if(jls->data == NULL)
+ err(1, "out of memory");
+
+ if(sysctlbyname("security.jail.list", jls->data, &jls->length, NULL, 0) == -1)
+ {
+ if(errno == ENOMEM)
+ {
+ free(jls->data);
+ jls->data = NULL;
+ goto retry;
+ }
+
+ err(1, "couldn't list jails");
+ }
+
+ xp = jls->data;
+ if(jls->length < sizeof(*xp) || xp->pr_version != XPRISON_VERSION)
+ errx(1, "kernel and userland out of sync");
}
-void free_jail_sysctl(size_t len, struct xprison* xp)
+struct xprison*
+jails_next (jails *jls)
{
- if(len == 0 || xp == NULL)
- return;
-
- /*
- * An extra precaution to prevent leakage of information
- * into the jail.
- */
-
- memset(xp, 0, sizeof(struct xprison) * len);
- free(xp);
+ struct xprison *xp = jls->last;
+ unsigned char *data, *next, *end;
+
+ if(xp == NULL)
+ {
+ xp = jls->data;
+ }
+ else
+ {
+ switch(xp->pr_version)
+ {
+ case 1:
+ case 2:
+ xp = xp + 1;
+ break;
+ case 3:
+ data = (unsigned char*)(xp + 1);
+ data += (xp->pr_ip4s * sizeof(struct in_addr));
+ data += (xp->pr_ip6s * sizeof(struct in6_addr));
+ xp = (struct xprison*)data;
+ break;
+ default:
+ errx(1, "unknown jail structure");
+ break;
+ }
+ }
+
+ if(xp == NULL)
+ return NULL;
+
+ next = (unsigned char*)(xp + 1);
+ end = ((unsigned char*)jls->data) + jls->length;
+ if (next > end)
+ return NULL;
+
+ if(xp->pr_version != XPRISON_VERSION)
+ errx(1, "kernel and userland out of sync");
+
+ jls->last = xp;
+ return xp;
}
-struct xprison* find_jail(const char* str, size_t len, struct xprison* xp)
+void
+jails_done(jails *jls)
{
- int jid;
- size_t i;
- char* e;
-
- if(len == 0 || xp == NULL)
- return NULL;
-
- 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)
- return &(xp[i]);
- }
- }
-
- for(i = 0; i < len; i++)
- {
- if(strcmp(xp[i].pr_host, str) == 0)
- return &(xp[i]);
- }
+ memset(jls->data, 0, jls->length);
+ free(jls->data);
+ jls->data = NULL;
+ jls->length = 0;
+ jls->last = NULL;
+}
- return NULL;
+struct xprison*
+jails_find(jails *jls, const char* str)
+{
+ struct xprison *xp;
+ char *e;
+ int jid;
+
+ jid = strtol(str, &e, 10);
+ jls->last = NULL;
+
+ for(;;)
+ {
+ xp = jails_next(jls);
+ if(xp == NULL)
+ return NULL;
+
+ /* If it was all a number ... */
+ if(!*e)
+ {
+ if(jid <= 0)
+ errx(1, "invalid jail id: %s", str);
+ if(jid == xp->pr_id)
+ return xp;
+ }
+
+ /* A host name? */
+ else
+ {
+ if(strcmp(xp->pr_host, str) == 0)
+ return xp;
+ }
+ }
+
+ /* Not reached */
}
int translate_jail_name(const char* str)
{
- struct xprison* sxp = NULL;
- struct xprison* xp = NULL;
- size_t len;
- int jid = -1;
-
- len = get_jail_sysctl(&sxp);
- if(sxp)
- {
- xp = find_jail(str, len, sxp);
- if(xp != NULL)
- jid = xp->pr_id;
+ struct xprison* xp;
+ int jid = -1;
+ jails jls;
- free(sxp);
- }
+ jails_load(&jls);
+ xp = jails_find(&jls, str);
+ if(xp != NULL)
+ jid = xp->pr_id;
+ jails_done(&jls);
- return jid;
+ return jid;
}
int kvm_prepare_jail(struct xprison* xp)
diff --git a/srcx/util.h b/srcx/util.h
index c98dad1..cc359b1 100644
--- a/srcx/util.h
+++ b/srcx/util.h
@@ -44,11 +44,16 @@ struct xprison;
int translate_jail_name(const char* str);
int running_in_jail();
-size_t get_jail_sysctl(struct xprison** xp);
-void free_jail_sysctl(size_t len, struct xprison* xp);
+typedef struct jails {
+ void *data;
+ size_t length;
+ struct xprison *last;
+} jails;
-int kvm_prepare_jail(struct xprison* xp);
-struct xprison* find_jail(const char* str, size_t len, struct xprison* xp);
+void jails_load(jails *jls);
+struct xprison* jails_next(jails *jls);
+struct xprison* jails_find(jails *jls, const char *str);
+void jails_done(jails *jls);
#define JAIL_RUN_CONSOLE 0x00000001 /* Output stuff to the jail console if available */
#define JAIL_RUN_STDOUT 0x00000002 /* Output to stdout */