Browse Source

Merge pull request #5778 from crosbymichael/check-symlink

Ensure libcontainer follows correct symlink in scope
Victor Vieux 11 years ago
parent
commit
f637eaca5d

+ 2 - 2
daemon/volumes.go

@@ -10,7 +10,7 @@ import (
 
 
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/daemon/execdriver"
 	"github.com/dotcloud/docker/daemon/execdriver"
-	"github.com/dotcloud/docker/utils"
+	"github.com/dotcloud/docker/pkg/symlink"
 )
 )
 
 
 type BindMap struct {
 type BindMap struct {
@@ -213,7 +213,7 @@ func createVolumes(container *Container) error {
 		}
 		}
 
 
 		// Create the mountpoint
 		// Create the mountpoint
-		rootVolPath, err := utils.FollowSymlinkInScope(filepath.Join(container.basefs, volPath), container.basefs)
+		rootVolPath, err := symlink.FollowSymlinkInScope(filepath.Join(container.basefs, volPath), container.basefs)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}

+ 7 - 0
pkg/libcontainer/mount/init.go

@@ -11,6 +11,7 @@ import (
 	"github.com/dotcloud/docker/pkg/label"
 	"github.com/dotcloud/docker/pkg/label"
 	"github.com/dotcloud/docker/pkg/libcontainer"
 	"github.com/dotcloud/docker/pkg/libcontainer"
 	"github.com/dotcloud/docker/pkg/libcontainer/mount/nodes"
 	"github.com/dotcloud/docker/pkg/libcontainer/mount/nodes"
+	"github.com/dotcloud/docker/pkg/symlink"
 	"github.com/dotcloud/docker/pkg/system"
 	"github.com/dotcloud/docker/pkg/system"
 )
 )
 
 
@@ -127,6 +128,12 @@ func setupBindmounts(rootfs string, bindMounts libcontainer.Mounts) error {
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
+
+		dest, err = symlink.FollowSymlinkInScope(dest, rootfs)
+		if err != nil {
+			return err
+		}
+
 		if err := createIfNotExists(dest, stat.IsDir()); err != nil {
 		if err := createIfNotExists(dest, stat.IsDir()); err != nil {
 			return fmt.Errorf("Creating new bind-mount target, %s", err)
 			return fmt.Errorf("Creating new bind-mount target, %s", err)
 		}
 		}

+ 2 - 0
pkg/symlink/MAINTAINERS

@@ -0,0 +1,2 @@
+Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
+Victor Vieux <vieux@docker.com> (@vieux)

+ 1 - 32
utils/fs.go → pkg/symlink/fs.go

@@ -1,43 +1,12 @@
-package utils
+package symlink
 
 
 import (
 import (
 	"fmt"
 	"fmt"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 	"strings"
 	"strings"
-	"syscall"
 )
 )
 
 
-// TreeSize walks a directory tree and returns its total size in bytes.
-func TreeSize(dir string) (size int64, err error) {
-	data := make(map[uint64]struct{})
-	err = filepath.Walk(dir, func(d string, fileInfo os.FileInfo, e error) error {
-		// Ignore directory sizes
-		if fileInfo == nil {
-			return nil
-		}
-
-		s := fileInfo.Size()
-		if fileInfo.IsDir() || s == 0 {
-			return nil
-		}
-
-		// Check inode to handle hard links correctly
-		inode := fileInfo.Sys().(*syscall.Stat_t).Ino
-		// inode is not a uint64 on all platforms. Cast it to avoid issues.
-		if _, exists := data[uint64(inode)]; exists {
-			return nil
-		}
-		// inode is not a uint64 on all platforms. Cast it to avoid issues.
-		data[uint64(inode)] = struct{}{}
-
-		size += s
-
-		return nil
-	})
-	return
-}
-
 // FollowSymlink will follow an existing link and scope it to the root
 // FollowSymlink will follow an existing link and scope it to the root
 // path provided.
 // path provided.
 func FollowSymlinkInScope(link, root string) (string, error) {
 func FollowSymlinkInScope(link, root string) (string, error) {

+ 1 - 1
utils/fs_test.go → pkg/symlink/fs_test.go

@@ -1,4 +1,4 @@
-package utils
+package symlink
 
 
 import (
 import (
 	"io/ioutil"
 	"io/ioutil"

+ 0 - 0
utils/testdata/fs/a/d → pkg/symlink/testdata/fs/a/d


+ 0 - 0
utils/testdata/fs/a/e → pkg/symlink/testdata/fs/a/e


+ 0 - 0
utils/testdata/fs/a/f → pkg/symlink/testdata/fs/a/f


+ 0 - 0
utils/testdata/fs/b/h → pkg/symlink/testdata/fs/b/h


+ 0 - 0
utils/testdata/fs/g → pkg/symlink/testdata/fs/g


+ 2 - 1
server/buildfile.go

@@ -20,6 +20,7 @@ import (
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/daemon"
 	"github.com/dotcloud/docker/daemon"
 	"github.com/dotcloud/docker/nat"
 	"github.com/dotcloud/docker/nat"
+	"github.com/dotcloud/docker/pkg/symlink"
 	"github.com/dotcloud/docker/registry"
 	"github.com/dotcloud/docker/registry"
 	"github.com/dotcloud/docker/runconfig"
 	"github.com/dotcloud/docker/runconfig"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
@@ -404,7 +405,7 @@ func (b *buildFile) addContext(container *daemon.Container, orig, dest string, r
 	)
 	)
 
 
 	if destPath != container.RootfsPath() {
 	if destPath != container.RootfsPath() {
-		destPath, err = utils.FollowSymlinkInScope(destPath, container.RootfsPath())
+		destPath, err = symlink.FollowSymlinkInScope(destPath, container.RootfsPath())
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}

+ 31 - 0
utils/utils.go

@@ -21,6 +21,7 @@ import (
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
+	"syscall"
 	"time"
 	"time"
 
 
 	"github.com/dotcloud/docker/dockerversion"
 	"github.com/dotcloud/docker/dockerversion"
@@ -1091,3 +1092,33 @@ func ParseKeyValueOpt(opt string) (string, string, error) {
 	}
 	}
 	return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
 	return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
 }
 }
+
+// TreeSize walks a directory tree and returns its total size in bytes.
+func TreeSize(dir string) (size int64, err error) {
+	data := make(map[uint64]struct{})
+	err = filepath.Walk(dir, func(d string, fileInfo os.FileInfo, e error) error {
+		// Ignore directory sizes
+		if fileInfo == nil {
+			return nil
+		}
+
+		s := fileInfo.Size()
+		if fileInfo.IsDir() || s == 0 {
+			return nil
+		}
+
+		// Check inode to handle hard links correctly
+		inode := fileInfo.Sys().(*syscall.Stat_t).Ino
+		// inode is not a uint64 on all platforms. Cast it to avoid issues.
+		if _, exists := data[uint64(inode)]; exists {
+			return nil
+		}
+		// inode is not a uint64 on all platforms. Cast it to avoid issues.
+		data[uint64(inode)] = struct{}{}
+
+		size += s
+
+		return nil
+	})
+	return
+}