Browse code

pkg: chrootarchive: chroot_linux: fix mount leak

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>

Antonio Murdaca authored on 2016/05/10 23:18:16
Showing 1 changed files
... ...
@@ -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
 		}