From 2188d81fdd47d96198cab7828808807d0593bf99 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Fri, 20 Mar 2020 18:19:53 +0000 Subject: [PATCH] jail: add support for launching extroot containers Add option to ujail to use an existing rootfs when launching a containerized service. Later on this option will also be used to launch full-system containers. Signed-off-by: Daniel Golle --- jail/jail.c | 45 ++++++++++++++++++++++++++++++++++----------- service/instance.c | 15 +++++++++++++++ service/instance.h | 1 + 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/jail/jail.c b/jail/jail.c index 5414519..df1bda7 100644 --- a/jail/jail.c +++ b/jail/jail.c @@ -40,7 +40,7 @@ #include #define STACK_SIZE (1024 * 1024) -#define OPT_ARGS "S:C:n:h:r:w:d:psulocU:G:N" +#define OPT_ARGS "S:C:n:h:r:w:d:psulocU:G:NR:" #define NAMESPACE_MOUNT (1U << 0) #define NAMESPACE_IPC (1U << 1) @@ -58,6 +58,7 @@ static struct { char *capabilities; char *user; char *group; + char *extroot; int no_new_privs; int namespace; int procfs; @@ -164,9 +165,16 @@ static int build_jail_fs(void) return -1; } - if (mount("tmpfs", jail_root, "tmpfs", MS_NOATIME, "mode=0755")) { - ERROR("tmpfs mount failed %m\n"); - return -1; + if (opts.extroot) { + if (mount(opts.extroot, jail_root, NULL, MS_BIND | MS_REC, NULL)) { + ERROR("extroot mount failed %m\n"); + return -1; + } + } else { + if (mount("tmpfs", jail_root, "tmpfs", MS_NOATIME, "mode=0755")) { + ERROR("tmpfs mount failed %m\n"); + return -1; + } } if (chdir(jail_root)) { @@ -230,6 +238,7 @@ static char** build_envp(const char *seccomp) static char preload_var[PATH_MAX]; static char seccomp_var[PATH_MAX]; static char debug_var[] = "LD_DEBUG=all"; + static char container_var[] = "container=ujail"; const char *preload_lib = find_lib("libpreload-seccomp.so"); int count = 0; @@ -243,6 +252,10 @@ static char** build_envp(const char *seccomp) snprintf(preload_var, sizeof(preload_var), "LD_PRELOAD=%s", preload_lib); envp[count++] = preload_var; } + + if (is_extroot) + envp[count++] = container_var; + if (debug > 1) envp[count++] = debug_var; @@ -269,6 +282,7 @@ static void usage(void) fprintf(stderr, " -U \tuser to run jailed process\n"); fprintf(stderr, " -G \tgroup to run jailed process\n"); fprintf(stderr, " -o\t\tremont jail root (/) read only\n"); + fprintf(stderr, " -R \texternal jail rootfs (system container)\n"); 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\ @@ -437,6 +451,10 @@ int main(int argc, char **argv) opts.namespace |= NAMESPACE_MOUNT; opts.ronly = 1; break; + case 'R': + opts.namespace |= NAMESPACE_MOUNT | NAMESPACE_UTS; + opts.extroot = optarg; + break; case 's': opts.namespace |= NAMESPACE_MOUNT; opts.sysfs = 1; @@ -502,14 +520,16 @@ int main(int argc, char **argv) opts.jail_argv = &argv[optind]; - if (opts.namespace && add_path_and_deps(*opts.jail_argv, 1, -1, 0)) { - ERROR("failed to load dependencies\n"); - return -1; - } + if (!opts.extroot) { + if (opts.namespace && add_path_and_deps(*opts.jail_argv, 1, -1, 0)) { + ERROR("failed to load dependencies\n"); + return -1; + } - if (opts.namespace && opts.seccomp && add_path_and_deps("libpreload-seccomp.so", 1, -1, 1)) { - ERROR("failed to load libpreload-seccomp.so\n"); - return -1; + if (opts.namespace && opts.seccomp && add_path_and_deps("libpreload-seccomp.so", 1, -1, 1)) { + ERROR("failed to load libpreload-seccomp.so\n"); + return -1; + } } if (opts.name) @@ -537,8 +557,11 @@ int main(int argc, char **argv) flags |= CLONE_NEWNS; add_mount("/dev/full", 0, -1); add_mount("/dev/null", 0, -1); + add_mount("/dev/random", 0, -1); add_mount("/dev/urandom", 0, -1); + add_mount("/dev/tty", 0, -1); add_mount("/dev/zero", 0, -1); + add_mount("/dev/console", 0, -1); if (opts.user || opts.group) { add_mount("/etc/passwd", 0, -1); diff --git a/service/instance.c b/service/instance.c index ffaaaa1..47b7d09 100644 --- a/service/instance.c +++ b/service/instance.c @@ -102,6 +102,7 @@ enum { JAIL_ATTR_MOUNT, JAIL_ATTR_NETNS, JAIL_ATTR_REQUIREJAIL, + JAIL_ATTR_EXTROOT, __JAIL_ATTR_MAX, }; @@ -116,6 +117,7 @@ static const struct blobmsg_policy jail_attr[__JAIL_ATTR_MAX] = { [JAIL_ATTR_MOUNT] = { "mount", BLOBMSG_TYPE_TABLE }, [JAIL_ATTR_NETNS] = { "netns", BLOBMSG_TYPE_BOOL }, [JAIL_ATTR_REQUIREJAIL] = { "requirejail", BLOBMSG_TYPE_BOOL }, + [JAIL_ATTR_EXTROOT] = { "extroot", BLOBMSG_TYPE_STRING }, }; struct instance_netdev { @@ -258,6 +260,11 @@ jail_run(struct service_instance *in, char **argv) if (jail->netns) argv[argc++] = "-N"; + if (jail->extroot) { + argv[argc++] = "-R"; + argv[argc++] = jail->extroot; + } + blobmsg_list_for_each(&jail->mount, var) { const char *type = blobmsg_data(var->data); @@ -863,6 +870,11 @@ instance_jail_parse(struct service_instance *in, struct blob_attr *attr) jail->netns = blobmsg_get_bool(tb[JAIL_ATTR_NETNS]); jail->argc++; } + if (tb[JAIL_ATTR_EXTROOT]) { + jail->extroot = strdup(blobmsg_get_string(tb[JAIL_ATTR_EXTROOT])); + jail->argc += 2; + } + if (tb[JAIL_ATTR_MOUNT]) { struct blob_attr *cur; int rem; @@ -1139,6 +1151,7 @@ instance_free(struct service_instance *in) free(in->config); free(in->user); free(in->group); + free(in->jail.extroot); free(in->jail.name); free(in->jail.hostname); free(in->seccomp); @@ -1262,6 +1275,8 @@ void instance_dump(struct blob_buf *b, struct service_instance *in, int verbose) blobmsg_add_string(b, "name", in->jail.name); if (in->jail.hostname) blobmsg_add_string(b, "hostname", in->jail.hostname); + if (in->jail.extroot) + blobmsg_add_string(b, "extroot", in->jail.extroot); blobmsg_add_u8(b, "procfs", in->jail.procfs); blobmsg_add_u8(b, "sysfs", in->jail.sysfs); blobmsg_add_u8(b, "ubus", in->jail.ubus); diff --git a/service/instance.h b/service/instance.h index 003a8c9..29406c9 100644 --- a/service/instance.h +++ b/service/instance.h @@ -32,6 +32,7 @@ struct jail { bool netns; char *name; char *hostname; + char *extroot; struct blobmsg_list mount; int argc; }; -- 2.30.2