summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2017-06-22 14:31:37 -0400
committerAtomic Bot <atomic-devel@projectatomic.io>2018-04-30 16:50:19 +0000
commit3ce7c8281fb535007949dca9035dab0194d0ea35 (patch)
tree694f4b384fa0ee3a5ca547d7c0f8c24c6d1f5e71
parentfbee75d5515540a030b264192bd0dbf089939904 (diff)
downloadbubblewrap-3ce7c8281fb535007949dca9035dab0194d0ea35.tar.gz
Use pivot_root() instead of chroot() for final root
This is preparatory work for supporting recursive bwrap. Without this, using `mount()` on the second `/` won't work, since it won't be a mount point. Closes: #256 Approved by: cgwalters
-rw-r--r--bubblewrap.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/bubblewrap.c b/bubblewrap.c
index 7766c61..c7b5ee6 100644
--- a/bubblewrap.c
+++ b/bubblewrap.c
@@ -2357,6 +2357,40 @@ main (int argc,
if (umount2 ("oldroot", MNT_DETACH))
die_with_error ("unmount old root");
+ /* This is our second pivot. It's like we're a Silicon Valley startup flush
+ * with cash but short on ideas!
+ *
+ * We're aiming to make /newroot the real root, and get rid of /oldroot. To do
+ * that we need a temporary place to store it before we can unmount it.
+ */
+ { cleanup_free char *pivot_tmp = xstrdup ("bwrap-pivot-old-XXXXXX");
+ if (mount ("/newroot", "/newroot", NULL, MS_MGC_VAL | MS_BIND | MS_REC, NULL) < 0)
+ die_with_error ("setting up newroot bind");
+ if (chdir ("/newroot") != 0)
+ die_with_error ("chdir /newroot");
+ if (mkdtemp (pivot_tmp) == NULL)
+ {
+ /* If the user did a bind mount of /, try /tmp */
+ if (errno == EROFS || errno == EPERM || errno == EACCES)
+ {
+ free (pivot_tmp);
+ pivot_tmp = xstrdup ("tmp/bwrap-pivot-old-XXXXXX");
+ if (mkdtemp (pivot_tmp) == NULL)
+ die_with_error ("mkdtemp");
+ }
+ else
+ die_with_error ("mkdtemp");
+ }
+ if (pivot_root (".", pivot_tmp) != 0)
+ die_with_error ("pivot_root(/newroot)");
+ if (chroot (".") != 0)
+ die_with_error ("chroot .");
+ if (chdir ("/") != 0)
+ die_with_error ("chdir /");
+ if (umount2 (pivot_tmp, MNT_DETACH) < 0)
+ die_with_error ("unmount old root");
+ }
+
if (opt_unshare_user &&
(ns_uid != opt_sandbox_uid || ns_gid != opt_sandbox_gid) &&
opt_userns_block_fd == -1)
@@ -2373,14 +2407,6 @@ main (int argc,
-1, FALSE, FALSE);
}
- /* Now make /newroot the real root */
- if (chdir ("/newroot") != 0)
- die_with_error ("chdir newroot");
- if (chroot ("/newroot") != 0)
- die_with_error ("chroot /newroot");
- if (chdir ("/") != 0)
- die_with_error ("chdir /");
-
/* All privileged ops are done now, so drop caps we don't need */
drop_privs (!is_privileged);