From 0014a12d960851b2bd79f679f475a22ee068ffcf Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Fri, 31 Oct 2014 12:14:32 +0300 Subject: [PATCH] zdtm: prepare a file tree for userns Here are two issues: 1. All mounts in a new user namespace are locked, so we need to create a new root mount. We need to bind-mount root to itself. 2. /proc and /sys must be mounted before umounting /proc and /sys which were inhereted. It's a security policy. """ Author: Eric W. Biederman Date: Sun Mar 24 14:28:27 2013 -0700 userns: Restrict when proc and sysfs can be mounted Only allow unprivileged mounts of proc and sysfs if they are already mounted when the user namespace is created. """ Signed-off-by: Andrey Vagin Signed-off-by: Pavel Emelyanov --- test/zdtm/lib/ns.c | 48 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c index a7e3261fd..9901f5f7f 100644 --- a/test/zdtm/lib/ns.c +++ b/test/zdtm/lib/ns.c @@ -19,8 +19,9 @@ extern int pivot_root(const char *new_root, const char *put_old); static int prepare_mntns() { - int dfd; + int dfd, ret; char *root; + char path[PATH_MAX]; root = getenv("ZDTM_ROOT"); if (!root) { @@ -28,7 +29,28 @@ static int prepare_mntns() return -1; } - dfd = open(".", O_RDONLY); + /* + * In a new userns all mounts are locked to protect what is + * under them. So we need to create another mount for the + * new root. + */ + if (mount("/", "/", NULL, MS_PRIVATE | MS_REC, NULL)) { + fprintf(stderr, "Can't bind-mount root: %m\n"); + return -1; + } + + if (mount(root, root, NULL, MS_BIND | MS_REC, NULL)) { + fprintf(stderr, "Can't bind-mount root: %m\n"); + return -1; + } + + /* Move current working directory to the new root */ + ret = readlink("/proc/self/cwd", path, sizeof(path) - 1); + if (ret < 0) + return -1; + path[ret] = 0; + + dfd = open(path, O_RDONLY | O_DIRECTORY); if (dfd == -1) { fprintf(stderr, "open(.) failed: %m\n"); return -1; @@ -43,27 +65,31 @@ static int prepare_mntns() return -1; } - if (mount("none", "/", "none", MS_REC|MS_PRIVATE, NULL)) { - fprintf(stderr, "Can't remount root with MS_PRIVATE: %m\n"); - return -1; - } - if (pivot_root(".", "./old")) { fprintf(stderr, "pivot_root(., ./old) failed: %m\n"); return -1; } - if (umount2("./old", MNT_DETACH)) { - fprintf(stderr, "umount(./old) failed: %m\n"); - return -1; - } + if (mkdir("proc", 0777) && errno != EEXIST) { fprintf(stderr, "mkdir(proc) failed: %m\n"); return -1; } + + /* + * proc and sysfs can be mounted in an unprivileged namespace, + * if they are already mounted when the user namespace is created. + * So ./old must be umounted after mounting /proc and /sys. + */ if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL)) { fprintf(stderr, "mount(/proc) failed: %m\n"); return -1; } + + if (umount2("./old", MNT_DETACH)) { + fprintf(stderr, "umount(./old) failed: %m\n"); + return -1; + } + if (mkdir("/dev", 0755) && errno != EEXIST) { fprintf(stderr, "mkdir(/dev) failed: %m\n"); return -1;