From 4bef00e8f39ef127ff8922d0931e7ffd95950d20 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Tue, 18 May 2004 16:23:45 +0000 Subject: Tested on FreeBSD 5.2.1. Fixed bugs. --- srcx/util.c | 233 ++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 134 insertions(+), 99 deletions(-) (limited to 'srcx/util.c') 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 -#include -#include #include +#include +#include +#include #include #include #include +#include #include #include @@ -16,26 +18,15 @@ #include #include -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); } + + + + + + -- cgit v1.2.3