From d7c46118482f7f1b114d67f7d7827868c7941fb0 Mon Sep 17 00:00:00 2001 From: Yanqiang Miao Date: Tue, 3 Oct 2017 12:44:46 +0800 Subject: [PATCH] Ensure getting the correct mountinfo corresponds to path Signed-off-by: Yanqiang Miao --- mount/lookup_test/lookup_linux_test.go | 31 ++++++++++++++++++++++++-- mount/lookup_unix.go | 11 ++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/mount/lookup_test/lookup_linux_test.go b/mount/lookup_test/lookup_linux_test.go index 19eef4ff8..852053369 100644 --- a/mount/lookup_test/lookup_linux_test.go +++ b/mount/lookup_test/lookup_linux_test.go @@ -13,6 +13,7 @@ import ( "io/ioutil" "os" "os/exec" + "path/filepath" "strings" "testing" @@ -22,6 +23,15 @@ import ( ) func testLookup(t *testing.T, fsType string) { + checkLookup := func(mntPoint, dir string) { + info, err := mount.Lookup(dir) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, fsType, info.FSType) + assert.Equal(t, mntPoint, info.Mountpoint) + } + testutil.RequiresRoot(t) mnt, err := ioutil.TempDir("", "containerd-mountinfo-test-lookup") if err != nil { @@ -46,11 +56,28 @@ func testLookup(t *testing.T, fsType string) { cleanupDevice() }() assert.True(t, strings.HasPrefix(deviceName, "/dev/loop")) - info, err := mount.Lookup(mnt) + checkLookup(mnt, mnt) + + newMnt, err := ioutil.TempDir("", "containerd-mountinfo-test-newMnt") if err != nil { t.Fatal(err) } - assert.Equal(t, fsType, info.FSType) + defer os.RemoveAll(newMnt) + + if out, err := exec.Command("mount", "--bind", mnt, newMnt).CombinedOutput(); err != nil { + t.Fatalf("could not mount %s to %s: %v (out: %q)", mnt, newMnt, err, string(out)) + } + defer func() { + testutil.Unmount(t, newMnt) + }() + checkLookup(newMnt, newMnt) + + subDir := filepath.Join(newMnt, "subDir") + err = os.MkdirAll(subDir, 0700) + if err != nil { + t.Fatal(err) + } + checkLookup(newMnt, subDir) } func TestLookupWithExt4(t *testing.T) { diff --git a/mount/lookup_unix.go b/mount/lookup_unix.go index ae1b6a337..df9625a96 100644 --- a/mount/lookup_unix.go +++ b/mount/lookup_unix.go @@ -4,6 +4,9 @@ package mount import ( "fmt" + "path/filepath" + "sort" + "strings" "syscall" "github.com/pkg/errors" @@ -12,6 +15,7 @@ import ( // Lookup returns the mount info corresponds to the path. func Lookup(dir string) (Info, error) { var dirStat syscall.Stat_t + dir = filepath.Clean(dir) if err := syscall.Stat(dir, &dirStat); err != nil { return Info{}, errors.Wrapf(err, "failed to access %q", dir) } @@ -20,6 +24,11 @@ func Lookup(dir string) (Info, error) { if err != nil { return Info{}, err } + + // Sort descending order by Info.Mountpoint + sort.Slice(mounts, func(i, j int) bool { + return mounts[j].Mountpoint < mounts[i].Mountpoint + }) for _, m := range mounts { // Note that m.{Major, Minor} are generally unreliable for our purpose here // https://www.spinics.net/lists/linux-btrfs/msg58908.html @@ -28,7 +37,7 @@ func Lookup(dir string) (Info, error) { // may fail; ignore err continue } - if st.Dev == dirStat.Dev { + if st.Dev == dirStat.Dev && strings.HasPrefix(dir, m.Mountpoint) { return m, nil } }