minijail: Support pivot_root
Add an option that allows user to use pivot_root(2) when one want to
jail process in a chrooted environment. This implies entering a new
mount namespace since pivot_root(2) will really move the root
filesystem.
BUG=chromium:517844
TEST=security_Minijail0 passes
Change-Id: Ie990670703b00e333fa4abc3804d6384d36fa7c9
Reviewed-on: https://chromium-review.googlesource.com/293128
Commit-Ready: Yu-hsi Chiang <yuhsi@google.com>
Tested-by: Yu-hsi Chiang <yuhsi@google.com>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
diff --git a/libminijail.c b/libminijail.c
index 5378d84..8e05094 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -95,6 +95,7 @@
int seccomp_filter:1;
int log_seccomp_filter:1;
int chroot:1;
+ int pivot_root:1;
int mount_tmp:1;
int do_init:1;
int pid_file:1;
@@ -362,6 +363,17 @@
return 0;
}
+int API minijail_enter_pivot_root(struct minijail *j, const char *dir)
+{
+ if (j->chrootdir)
+ return -EINVAL;
+ j->chrootdir = strdup(dir);
+ if (!j->chrootdir)
+ return -ENOMEM;
+ j->flags.pivot_root = 1;
+ return 0;
+}
+
void API minijail_mount_tmp(struct minijail *j)
{
j->flags.mount_tmp = 1;
@@ -730,6 +742,36 @@
return 0;
}
+int enter_pivot_root(const struct minijail *j)
+{
+ int ret;
+ if (j->bindings_head && (ret = bind_one(j, j->bindings_head)))
+ return ret;
+
+ /* To ensure chrootdir is the root of a file system, do a self bind mount. */
+ if (mount(j->chrootdir, j->chrootdir, "bind", MS_BIND | MS_REC, ""))
+ pdie("failed to bind mount '%s'", j->chrootdir);
+ if (chdir(j->chrootdir))
+ return -errno;
+ if (mkdir(".minijail_pivot", 0755))
+ pdie("mkdir(.minijail_pivot)");
+ if (syscall(SYS_pivot_root, ".", ".minijail_pivot")) {
+ remove(".minijail_pivot");
+ pdie("pivot_root");
+ }
+ /* The old root might be busy, so use lazy unmount. */
+ if (umount2(".minijail_pivot", MNT_DETACH))
+ pdie("umount(.minijail_pivot");
+ if (chdir("/"))
+ return -errno;
+ if (chroot("/"))
+ return -errno;
+ if (remove(".minijail_pivot"))
+ return -errno;
+
+ return 0;
+}
+
int mount_tmp(void)
{
return mount("none", "/tmp", "tmpfs", 0, "size=64M,mode=777");
@@ -927,6 +969,9 @@
if (j->flags.chroot && enter_chroot(j))
pdie("chroot");
+ if (j->flags.pivot_root && enter_pivot_root(j))
+ pdie("pivot_root");
+
if (j->flags.mount_tmp && mount_tmp())
pdie("mount_tmp");