When pivot_root fails we need to unmount the bind mounted path we
previously mounted in preparation for pivot_root.
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
| ... | ... |
@@ -6,6 +6,8 @@ import ( |
| 6 | 6 |
"os" |
| 7 | 7 |
"path/filepath" |
| 8 | 8 |
"syscall" |
| 9 |
+ |
|
| 10 |
+ "github.com/docker/docker/pkg/mount" |
|
| 9 | 11 |
) |
| 10 | 12 |
|
| 11 | 13 |
// chroot on linux uses pivot_root instead of chroot |
| ... | ... |
@@ -15,13 +17,12 @@ import ( |
| 15 | 15 |
// Old root is removed after the call to pivot_root so it is no longer available under the new root. |
| 16 | 16 |
// This is similar to how libcontainer sets up a container's rootfs |
| 17 | 17 |
func chroot(path string) (err error) {
|
| 18 |
- // Create new mount namespace so mounts don't leak |
|
| 19 | 18 |
if err := syscall.Unshare(syscall.CLONE_NEWNS); err != nil {
|
| 20 | 19 |
return fmt.Errorf("Error creating mount namespace before pivot: %v", err)
|
| 21 | 20 |
} |
| 22 |
- // path must be a different fs for pivot_root, so bind-mount to itself to ensure this |
|
| 23 |
- if err := syscall.Mount(path, path, "", syscall.MS_BIND, ""); err != nil {
|
|
| 24 |
- return fmt.Errorf("Error mounting pivot dir before pivot: %v", err)
|
|
| 21 |
+ |
|
| 22 |
+ if err := mount.MakeRPrivate(path); err != nil {
|
|
| 23 |
+ return err |
|
| 25 | 24 |
} |
| 26 | 25 |
|
| 27 | 26 |
// setup oldRoot for pivot_root |
| ... | ... |
@@ -44,17 +45,24 @@ func chroot(path string) (err error) {
|
| 44 | 44 |
|
| 45 | 45 |
errCleanup := os.Remove(pivotDir) |
| 46 | 46 |
// pivotDir doesn't exist if pivot_root failed and chroot+chdir was successful |
| 47 |
- // but we already cleaned it up on failed pivot_root |
|
| 47 |
+ // because we already cleaned it up on failed pivot_root |
|
| 48 | 48 |
if errCleanup != nil && !os.IsNotExist(errCleanup) {
|
| 49 | 49 |
errCleanup = fmt.Errorf("Error cleaning up after pivot: %v", errCleanup)
|
| 50 | 50 |
if err == nil {
|
| 51 | 51 |
err = errCleanup |
| 52 | 52 |
} |
| 53 | 53 |
} |
| 54 |
+ |
|
| 55 |
+ if errCleanup := syscall.Unmount("/", syscall.MNT_DETACH); errCleanup != nil {
|
|
| 56 |
+ if err == nil {
|
|
| 57 |
+ err = fmt.Errorf("error unmounting root: %v", errCleanup)
|
|
| 58 |
+ } |
|
| 59 |
+ return |
|
| 60 |
+ } |
|
| 54 | 61 |
}() |
| 55 | 62 |
|
| 56 | 63 |
if err := syscall.PivotRoot(path, pivotDir); err != nil {
|
| 57 |
- // If pivot fails, fall back to the normal chroot after cleaning up temp dir for pivot_root |
|
| 64 |
+ // If pivot fails, fall back to the normal chroot after cleaning up temp dir |
|
| 58 | 65 |
if err := os.Remove(pivotDir); err != nil {
|
| 59 | 66 |
return fmt.Errorf("Error cleaning up after failed pivot: %v", err)
|
| 60 | 67 |
} |