summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEtienne CHAMPETIER <champetier.etienne@gmail.com>2015-08-27 01:26:47 +0200
committerJohn Crispin <blogic@openwrt.org>2015-10-07 11:08:06 +0200
commit25b58f2d549c0fb67e33849c2fc14106f667f404 (patch)
tree3dac4ded6417128426ef599a5f785544af011cf3
parentbfd963313f155846b4f6269bbc76161f81e1e99f (diff)
downloadunitd-25b58f2d549c0fb67e33849c2fc14106f667f404.tar
unitd-25b58f2d549c0fb67e33849c2fc14106f667f404.zip
jail: allow to not use namespaces
building a generic jail can be hard, choosing to drop some capabilities can be easier. This commit permit to use namespaces, capabilities and seccomp combined as you like. Signed-off-by: Etienne CHAMPETIER <champetier.etienne@gmail.com>
-rw-r--r--jail/jail.c76
1 files changed, 56 insertions, 20 deletions
diff --git a/jail/jail.c b/jail/jail.c
index 40b7558..f459a5e 100644
--- a/jail/jail.c
+++ b/jail/jail.c
@@ -42,6 +42,7 @@ static struct {
char **jail_argv;
char *seccomp;
char *capabilities;
+ int namespace;
int procfs;
int ronly;
int sysfs;
@@ -233,13 +234,14 @@ static char** build_envp(const char *seccomp)
static void usage(void)
{
fprintf(stderr, "ujail <options> -- <binary> <params ...>\n");
- fprintf(stderr, " -P <path>\tpath where the jail will be staged\n");
- fprintf(stderr, " -S <file>\tseccomp filter\n");
+ fprintf(stderr, " -d <num>\tshow debug log (increase num to increase verbosity)\n");
+ fprintf(stderr, " -S <file>\tseccomp filter config\n");
fprintf(stderr, " -C <file>\tcapabilities drop config\n");
fprintf(stderr, " -n <name>\tthe name of the jail\n");
+ fprintf(stderr, "namespace jail options:\n");
+ fprintf(stderr, " -P <path>\tpath where the jail will be staged\n");
fprintf(stderr, " -r <file>\treadonly files that should be staged\n");
fprintf(stderr, " -w <file>\twriteable files that should be staged\n");
- fprintf(stderr, " -d <num>\tshow debug log (increase num to increase verbosity)\n");
fprintf(stderr, " -p\t\tjail has /proc\n");
fprintf(stderr, " -s\t\tjail has /sys\n");
fprintf(stderr, " -l\t\tjail has /dev/log\n");
@@ -248,20 +250,14 @@ static void usage(void)
fprintf(stderr, "\nWarning: by default root inside the jail is the same\n\
and he has the same powers as root outside the jail,\n\
thus he can escape the jail and/or break stuff.\n\
-Please use an appropriate seccomp/capabilities filter (-S/-C) to restrict his powers\n");
+Please use seccomp/capabilities (-S/-C) to restrict his powers\n\n\
+If you use none of the namespace jail options,\n\
+ujail will not use namespace/build a jail,\n\
+and will only drop capabilities/apply seccomp filter.\n\n");
}
-static int spawn_jail(void *arg)
+static int exec_jail()
{
- if (opts.name && sethostname(opts.name, strlen(opts.name))) {
- ERROR("failed to sethostname: %s\n", strerror(errno));
- }
-
- if (build_jail_fs()) {
- ERROR("failed to build jail fs");
- exit(EXIT_FAILURE);
- }
-
char **envp = build_envp(opts.seccomp);
if (!envp)
exit(EXIT_FAILURE);
@@ -276,6 +272,20 @@ static int spawn_jail(void *arg)
exit(EXIT_FAILURE);
}
+static int spawn_jail(void *arg)
+{
+ if (opts.name && sethostname(opts.name, strlen(opts.name))) {
+ ERROR("failed to sethostname: %s\n", strerror(errno));
+ }
+
+ if (build_jail_fs()) {
+ ERROR("failed to build jail fs");
+ exit(EXIT_FAILURE);
+ }
+
+ return exec_jail();
+}
+
static int jail_running = 1;
static int jail_return_code = 0;
@@ -335,12 +345,15 @@ int main(int argc, char **argv)
debug = atoi(optarg);
break;
case 'p':
+ opts.namespace = 1;
opts.procfs = 1;
break;
case 'o':
+ opts.namespace = 1;
opts.ronly = 1;
break;
case 's':
+ opts.namespace = 1;
opts.sysfs = 1;
break;
case 'S':
@@ -352,21 +365,26 @@ int main(int argc, char **argv)
add_extra(optarg, 1);
break;
case 'P':
+ opts.namespace = 1;
opts.path = optarg;
break;
case 'n':
opts.name = optarg;
break;
case 'r':
+ opts.namespace = 1;
add_extra(optarg, 1);
break;
case 'w':
+ opts.namespace = 1;
add_extra(optarg, 0);
break;
case 'u':
+ opts.namespace = 1;
add_extra(ubus, 0);
break;
case 'l':
+ opts.namespace = 1;
add_extra(log, 0);
break;
}
@@ -377,41 +395,59 @@ int main(int argc, char **argv)
usage();
return EXIT_FAILURE;
}
+ if (!(opts.namespace||opts.capabilities||opts.seccomp)) {
+ ERROR("Not using namespaces, capabilities or seccomp !!!\n\n");
+ usage();
+ return EXIT_FAILURE;
+ }
+ DEBUG("Using namespaces(%d), capabilities(%d), seccomp(%d)\n",
+ opts.namespace,
+ opts.capabilities != 0,
+ opts.seccomp != 0);
opts.jail_argv = &argv[optind];
if (opts.name)
prctl(PR_SET_NAME, opts.name, NULL, NULL, NULL);
- if (!opts.path && asprintf(&opts.path, "/tmp/%s", basename(*opts.jail_argv)) == -1) {
+ if (opts.namespace && !opts.path && asprintf(&opts.path, "/tmp/%s", basename(*opts.jail_argv)) == -1) {
ERROR("failed to asprintf root path: %s\n", strerror(errno));
return EXIT_FAILURE;
}
- if (mkdir(opts.path, 0755)) {
+ if (opts.namespace && mkdir(opts.path, 0755)) {
ERROR("unable to create root path: %s (%s)\n", opts.path, strerror(errno));
return EXIT_FAILURE;
}
uloop_init();
- jail_process.pid = clone(spawn_jail,
+ if (opts.namespace) {
+ jail_process.pid = clone(spawn_jail,
child_stack + STACK_SIZE,
CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | SIGCHLD, argv);
+ } else {
+ jail_process.pid = fork();
+ }
- if (jail_process.pid != -1) {
+ if (jail_process.pid > 0) {
+ //parent process
uloop_process_add(&jail_process);
uloop_run();
uloop_done();
if (jail_running) {
+ DEBUG("uloop interrupted, killing jail process\n");
kill(jail_process.pid, SIGTERM);
waitpid(jail_process.pid, NULL, 0);
}
+ } else if (jail_process.pid == 0) {
+ //fork child process
+ return exec_jail();
} else {
- ERROR("failed to spawn namespace: %s\n", strerror(errno));
+ ERROR("failed to clone/fork: %s\n", strerror(errno));
ret = EXIT_FAILURE;
}
- if (rmdir(opts.path)) {
+ if (opts.namespace && rmdir(opts.path)) {
ERROR("Unable to remove root path: %s (%s)\n", opts.path, strerror(errno));
ret = EXIT_FAILURE;
}