1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Improve FollowLink to handle recursive link and be more strick

This commit is contained in:
Guillaume J. Charmes 2013-12-11 17:12:53 -08:00
parent f396c42cad
commit 8fd9633a6b
No known key found for this signature in database
GPG key ID: B33E4642CB6E3FF3
5 changed files with 52 additions and 41 deletions

View file

@ -827,7 +827,7 @@ func (container *Container) createVolumes() error {
// Create the mountpoint // Create the mountpoint
volPath = path.Join(container.RootfsPath(), volPath) volPath = path.Join(container.RootfsPath(), volPath)
rootVolPath, err := utils.FollowSymlink(volPath, container.RootfsPath()) rootVolPath, err := utils.FollowSymlinkInScope(volPath, container.RootfsPath())
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -1,6 +1,7 @@
package utils package utils
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -38,43 +39,52 @@ func TreeSize(dir string) (size int64, err error) {
// 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) {
prev := "." prev := "/"
root, err := filepath.Abs(root) root, err := filepath.Abs(root)
if err != nil { if err != nil {
return "", err return "", err
} }
root = filepath.Clean(root)
link, err := filepath.Abs(link) link, err = filepath.Abs(link)
if err != nil { if err != nil {
return "", err return "", err
} }
link = filepath.Clean(link)
if !strings.HasPrefix(filepath.Dir(link), root) {
return "", fmt.Errorf("%s is not within %s", link, root)
}
for _, p := range strings.Split(link, "/") { for _, p := range strings.Split(link, "/") {
prev = filepath.Join(prev, p) prev = filepath.Join(prev, p)
prev = filepath.Clean(prev) prev = filepath.Clean(prev)
stat, err := os.Lstat(prev) for {
if err != nil { stat, err := os.Lstat(prev)
if os.IsNotExist(err) {
continue
}
return "", err
}
if stat.Mode()&os.ModeSymlink == os.ModeSymlink {
dest, err := os.Readlink(prev)
if err != nil { if err != nil {
if os.IsNotExist(err) {
break
}
return "", err return "", err
} }
if stat.Mode()&os.ModeSymlink == os.ModeSymlink {
switch dest[0] { dest, err := os.Readlink(prev)
case '/': if err != nil {
prev = filepath.Join(root, dest) return "", err
case '.':
if prev = filepath.Clean(filepath.Join(filepath.Dir(prev), dest)); len(prev) < len(root) {
prev = filepath.Join(root, filepath.Base(dest))
} }
switch dest[0] {
case '/':
prev = filepath.Join(root, dest)
case '.':
prev, _ = filepath.Abs(prev)
if prev = filepath.Clean(filepath.Join(filepath.Dir(prev), dest)); len(prev) < len(root) {
prev = filepath.Join(root, filepath.Base(dest))
}
}
} else {
break
} }
} }
} }

View file

@ -1,15 +1,14 @@
package utils package utils
import ( import (
"os"
"path/filepath" "path/filepath"
"testing" "testing"
) )
func abs(p string) string { func abs(t *testing.T, p string) string {
o, err := filepath.Abs(p) o, err := filepath.Abs(p)
if err != nil { if err != nil {
panic(err) t.Fatal(err)
} }
return o return o
} }
@ -17,36 +16,31 @@ func abs(p string) string {
func TestFollowSymLinkNormal(t *testing.T) { func TestFollowSymLinkNormal(t *testing.T) {
link := "testdata/fs/a/d/c/data" link := "testdata/fs/a/d/c/data"
rewrite, err := FollowSymlink(link, "test") rewrite, err := FollowSymlinkInScope(link, "testdata")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if expected := abs("test/b/c/data"); expected != rewrite { if expected := abs(t, "testdata/b/c/data"); expected != rewrite {
t.Fatalf("Expected %s got %s", expected, rewrite) t.Fatalf("Expected %s got %s", expected, rewrite)
} }
} }
func TestFollowSymLinkRandomString(t *testing.T) { func TestFollowSymLinkRandomString(t *testing.T) {
rewrite, err := FollowSymlink("toto", "test") if _, err := FollowSymlinkInScope("toto", "testdata"); err == nil {
if err != nil { t.Fatal("Random string should fail but didn't")
t.Fatal(err)
}
if rewrite != "toto" {
t.Fatalf("Expected toto got %s", rewrite)
} }
} }
func TestFollowSymLinkLastLink(t *testing.T) { func TestFollowSymLinkLastLink(t *testing.T) {
link := "testdata/fs/a/d" link := "testdata/fs/a/d"
rewrite, err := FollowSymlink(link, "test") rewrite, err := FollowSymlinkInScope(link, "testdata")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if expected := abs("test/b"); expected != rewrite { if expected := abs(t, "testdata/b"); expected != rewrite {
t.Fatalf("Expected %s got %s", expected, rewrite) t.Fatalf("Expected %s got %s", expected, rewrite)
} }
} }
@ -54,31 +48,36 @@ func TestFollowSymLinkLastLink(t *testing.T) {
func TestFollowSymLinkRelativeLink(t *testing.T) { func TestFollowSymLinkRelativeLink(t *testing.T) {
link := "testdata/fs/a/e/c/data" link := "testdata/fs/a/e/c/data"
rewrite, err := FollowSymlink(link, "test") rewrite, err := FollowSymlinkInScope(link, "testdata")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if expected := abs("testdata/fs/a/e/c/data"); expected != rewrite { if expected := abs(t, "testdata/fs/b/c/data"); expected != rewrite {
t.Fatalf("Expected %s got %s", expected, rewrite) t.Fatalf("Expected %s got %s", expected, rewrite)
} }
} }
func TestFollowSymLinkRelativeLinkScope(t *testing.T) { func TestFollowSymLinkRelativeLinkScope(t *testing.T) {
link := "testdata/fs/a/f" link := "testdata/fs/a/f"
pwd, err := os.Getwd()
rewrite, err := FollowSymlinkInScope(link, "testdata")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
root := filepath.Join(pwd, "testdata") if expected := abs(t, "testdata/test"); expected != rewrite {
t.Fatalf("Expected %s got %s", expected, rewrite)
}
rewrite, err := FollowSymlink(link, root) link = "testdata/fs/b/h"
rewrite, err = FollowSymlinkInScope(link, "testdata")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if expected := abs("testdata/test"); expected != rewrite { if expected := abs(t, "testdata/root"); expected != rewrite {
t.Fatalf("Expected %s got %s", expected, rewrite) t.Fatalf("Expected %s got %s", expected, rewrite)
} }
} }

1
utils/testdata/fs/b/h vendored Symbolic link
View file

@ -0,0 +1 @@
../g

1
utils/testdata/fs/g vendored Symbolic link
View file

@ -0,0 +1 @@
../../../../../../../../../../../../root