From d04af54d5b0bf34c71c4695716e480a171b5a32b Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Wed, 18 Mar 2009 20:35:09 +0000 Subject: Changes that support FreeBSD 7.2 --- srcx/util.c | 211 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 127 insertions(+), 84 deletions(-) (limited to 'srcx/util.c') 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 #include +#include + #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) -- cgit v1.2.3