Commit 0014a12d authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

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 <ebiederm@xmission.com>
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: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent ed5a1ba1
...@@ -19,8 +19,9 @@ ...@@ -19,8 +19,9 @@
extern int pivot_root(const char *new_root, const char *put_old); extern int pivot_root(const char *new_root, const char *put_old);
static int prepare_mntns() static int prepare_mntns()
{ {
int dfd; int dfd, ret;
char *root; char *root;
char path[PATH_MAX];
root = getenv("ZDTM_ROOT"); root = getenv("ZDTM_ROOT");
if (!root) { if (!root) {
...@@ -28,7 +29,28 @@ static int prepare_mntns() ...@@ -28,7 +29,28 @@ static int prepare_mntns()
return -1; 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) { if (dfd == -1) {
fprintf(stderr, "open(.) failed: %m\n"); fprintf(stderr, "open(.) failed: %m\n");
return -1; return -1;
...@@ -43,27 +65,31 @@ static int prepare_mntns() ...@@ -43,27 +65,31 @@ static int prepare_mntns()
return -1; 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")) { if (pivot_root(".", "./old")) {
fprintf(stderr, "pivot_root(., ./old) failed: %m\n"); fprintf(stderr, "pivot_root(., ./old) failed: %m\n");
return -1; return -1;
} }
if (umount2("./old", MNT_DETACH)) {
fprintf(stderr, "umount(./old) failed: %m\n");
return -1;
}
if (mkdir("proc", 0777) && errno != EEXIST) { if (mkdir("proc", 0777) && errno != EEXIST) {
fprintf(stderr, "mkdir(proc) failed: %m\n"); fprintf(stderr, "mkdir(proc) failed: %m\n");
return -1; 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)) { if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL)) {
fprintf(stderr, "mount(/proc) failed: %m\n"); fprintf(stderr, "mount(/proc) failed: %m\n");
return -1; return -1;
} }
if (umount2("./old", MNT_DETACH)) {
fprintf(stderr, "umount(./old) failed: %m\n");
return -1;
}
if (mkdir("/dev", 0755) && errno != EEXIST) { if (mkdir("/dev", 0755) && errno != EEXIST) {
fprintf(stderr, "mkdir(/dev) failed: %m\n"); fprintf(stderr, "mkdir(/dev) failed: %m\n");
return -1; return -1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment