Created
October 4, 2017 10:54
-
-
Save dbnicholson/da8aa72ea3bd7ee8731c9da2792fd5a3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/bind-mount.c b/bind-mount.c | |
index 7d3543f..d069c96 100644 | |
--- a/bind-mount.c | |
+++ b/bind-mount.c | |
@@ -438,3 +438,27 @@ bind_mount (int proc_fd, | |
return 0; | |
} | |
+ | |
+bool | |
+mount_exists (int proc_fd, | |
+ const char *path) | |
+{ | |
+ cleanup_free char *resolved_path = NULL; | |
+ cleanup_mount_tab MountTab mount_tab = NULL; | |
+ | |
+ /* The mount operation will resolve any symlinks in the destination | |
+ path, so to find it in the mount table we need to do that too. */ | |
+ resolved_path = realpath (path, NULL); | |
+ if (resolved_path == NULL) | |
+ return FALSE; | |
+ | |
+ mount_tab = parse_mountinfo (proc_fd, resolved_path); | |
+ if (mount_tab[0].mountpoint == NULL) | |
+ { | |
+ /* No mountpoint at dest */ | |
+ errno = ENOENT; | |
+ return FALSE; | |
+ } | |
+ | |
+ return TRUE; | |
+} | |
diff --git a/bind-mount.h b/bind-mount.h | |
index c763763..b0f468a 100644 | |
--- a/bind-mount.h | |
+++ b/bind-mount.h | |
@@ -28,3 +28,6 @@ int bind_mount (int proc_fd, | |
const char *src, | |
const char *dest, | |
bind_option_t options); | |
+ | |
+bool mount_exists (int proc_fd, | |
+ const char *path); | |
diff --git a/bubblewrap.c b/bubblewrap.c | |
index 6e04459..8371fb9 100644 | |
--- a/bubblewrap.c | |
+++ b/bubblewrap.c | |
@@ -1853,12 +1853,32 @@ main (int argc, | |
/* Need to do this before the chroot, but after we're the real uid */ | |
resolve_symlinks_in_ops (); | |
- /* Mark everything as slave, so that we still | |
- * receive mounts from the real root, but don't | |
- * propagate mounts to the real root. */ | |
+ if (!mount_exists (proc_fd, "/")) | |
+ { | |
+ printf("No / mount\n"); | |
+ if (errno != ENOENT) | |
+ die_with_error ("Failed to get mount entry for /"); | |
+ | |
+ /* No / mount, likely in a chroot. Bind mount / to itself so that | |
+ * the subsequent slave mark succeeds. */ | |
+ if (mount ("/", "/", NULL, MS_BIND| MS_REC, NULL) < 0) | |
+ die_with_error ("Failed to mount /"); | |
+ } | |
+ | |
+ /* Mark everything as slave, so that we still receive mounts from the | |
+ * real root, but don't propagate mounts to the real root. This also | |
+ * satisfies the pivot_root requirement that the old root mount is not | |
+ * shared. */ | |
if (mount (NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) | |
die_with_error ("Failed to make / slave"); | |
+ /* pivot_root requires that both the old root and its parent are not | |
+ * shared mounts. To ensure control of the parent mount, bind mount / | |
+ * to itself. Since / was marked as slave above, both mounts will be | |
+ * non-shared. */ | |
+ if (mount ("/", "/", NULL, MS_BIND| MS_REC, NULL) < 0) | |
+ die_with_error ("Failed to bind mount / to itself"); | |
+ | |
/* Create a tmpfs which we will use as / in the namespace */ | |
if (mount ("", base_path, "tmpfs", MS_NODEV | MS_NOSUID, NULL) != 0) | |
die_with_error ("Failed to mount tmpfs"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment