diff options
author | Colin Walters <walters@verbum.org> | 2017-06-22 14:31:37 -0400 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-04-30 16:50:19 +0000 |
commit | 3ce7c8281fb535007949dca9035dab0194d0ea35 (patch) | |
tree | 694f4b384fa0ee3a5ca547d7c0f8c24c6d1f5e71 | |
parent | fbee75d5515540a030b264192bd0dbf089939904 (diff) | |
download | bubblewrap-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.c | 42 |
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); |