New option pivot_root_only to support nested namespaces
authorStephen Röttger <stephen.roettger@gmail.com>
Sun, 25 Sep 2016 07:30:08 +0000 (09:30 +0200)
committerStephen Röttger <sroettger@google.com>
Fri, 30 Sep 2016 14:30:59 +0000 (16:30 +0200)
If pivot_root_only is setthe chroot in the job setup will be skipped.

cmdline.c
common.h
mount.c

index 84a60526605252c9cd962cfa7742e9f272b180db..58b4335adf781ef2eb627d285fc2d5478223dc6b 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -108,7 +108,7 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
             "max_conns_per_ip:%u, uid:(ns:%u, global:%u), gid:(ns:%u, global:%u), time_limit:%ld, personality:%#lx, daemonize:%s, "
             "clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
             "clone_newipc:%s, clonew_newuts:%s, clone_newcgroup:%s, apply_sandbox:%s, keep_caps:%s, "
-            "tmpfs_size:%zu, disable_no_new_privs:%s",
+            "tmpfs_size:%zu, disable_no_new_privs:%s, pivot_root_only:%s",
             nsjconf->hostname, nsjconf->chroot, nsjconf->argv[0], nsjconf->bindhost, nsjconf->port,
             nsjconf->max_conns_per_ip, nsjconf->inside_uid, nsjconf->outside_uid,
             nsjconf->inside_gid, nsjconf->outside_gid, nsjconf->tlimit, nsjconf->personality,
@@ -117,7 +117,7 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
             logYesNo(nsjconf->clone_newpid), logYesNo(nsjconf->clone_newipc),
             logYesNo(nsjconf->clone_newuts), logYesNo(nsjconf->clone_newcgroup),
             logYesNo(nsjconf->apply_sandbox), logYesNo(nsjconf->keep_caps), nsjconf->tmpfs_size,
-            logYesNo(nsjconf->disable_no_new_privs));
+            logYesNo(nsjconf->disable_no_new_privs), logYesNo(nsjconf->pivot_root_only));
 
        {
                struct mounts_t *p;
@@ -282,6 +282,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                .daemonize = false,
                .tlimit = 0,
                .apply_sandbox = true,
+               .pivot_root_only = false,
                .verbose = false,
                .keep_caps = false,
                .disable_no_new_privs = false,
@@ -374,6 +375,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                {{"disable_sandbox", no_argument, NULL, 0x0503}, "Don't enable the seccomp-bpf sandboxing"},
                {{"skip_setsid", no_argument, NULL, 0x0504}, "Don't call setsid(), allows for terminal signal handling in the sandboxed process"},
                {{"pass_fd", required_argument, NULL, 0x0505}, "Don't close this FD before executing child (can be specified multiple times), by default: 0/1/2 are kept open"},
+               {{"pivot_root_only", no_argument, NULL, 0x0506}, "Only perform pivot_root, no chroot. This will enable nested namespaces"},
                {{"disable_no_new_privs", no_argument, NULL, 0x0507}, "Don't set the prctl(NO_NEW_PRIVS, 1) (DANGEROUS)"},
                {{"rlimit_as", required_argument, NULL, 0x0201}, "RLIMIT_AS in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 512)"},
                {{"rlimit_core", required_argument, NULL, 0x0202}, "RLIMIT_CORE in MB, 'max' for RLIM_INFINITY, 'def' for the current value (default: 0)"},
@@ -550,6 +552,9 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                                TAILQ_INSERT_HEAD(&nsjconf->open_fds, f, pointers);
                        }
                        break;
+               case 0x0506:
+                       nsjconf->pivot_root_only = true;
+                       break;
                case 0x0507:
                        nsjconf->disable_no_new_privs = true;
                        break;
index 0cbe49c0dd501ca8d394665ef1f7af13b04434ff..c8f52a4bec6393bfad90d9794fd4565a557cd7b3 100644 (file)
--- a/common.h
+++ b/common.h
@@ -105,6 +105,7 @@ struct nsjconf_t {
        bool daemonize;
        time_t tlimit;
        bool apply_sandbox;
+       bool pivot_root_only;
        bool verbose;
        bool keep_env;
        bool keep_caps;
diff --git a/mount.c b/mount.c
index 6f7bd818d16bd9b9242ce07a668c42129f2b9d5b..97a50a0fb01f683479970999de0d7c27d568df61 100644 (file)
--- a/mount.c
+++ b/mount.c
@@ -190,10 +190,15 @@ static bool mountInitNsInternal(struct nsjconf_t *nsjconf)
                return false;
        }
 
-       const char *const newrootdir = "/new_root";
-       if (mkdir(newrootdir, 0755) == -1) {
-               PLOG_E("mkdir('%s')", newrootdir);
-               return false;
+       const char *newrootdir;
+       if (nsjconf->pivot_root_only == false) {
+               newrootdir = "/new_root";
+               if (mkdir(newrootdir, 0755) == -1) {
+                       PLOG_E("mkdir('%s')", newrootdir);
+                       return false;
+               }
+       } else {
+               newrootdir = "/";
        }
 
        struct mounts_t *p;
@@ -209,9 +214,11 @@ static bool mountInitNsInternal(struct nsjconf_t *nsjconf)
                PLOG_E("umount2('/old_root', MNT_DETACH)");
                return false;
        }
-       if (chroot(newrootdir) == -1) {
-               PLOG_E("chroot('%s')", newrootdir);
-               return false;
+       if (nsjconf->pivot_root_only == false) {
+               if (chroot(newrootdir) == -1) {
+                       PLOG_E("chroot('%s')", newrootdir);
+                       return false;
+               }
        }
 
        if (chdir(nsjconf->cwd) == -1) {