From af9dab70f8ed6dd0284bd138bf60caded48a1b91 Mon Sep 17 00:00:00 2001 From: "Daniel, Dao Quang Minh" Date: Thu, 26 Mar 2015 06:02:21 +0000 Subject: [PATCH] aufs: apply dirperm1 by default if supported Automatically detect support for aufs `dirperm1` option and apply it. `dirperm1` tells aufs to check the permission bits of the directory on the topmost branch and ignore the permission bits on all lower branches. It can be used to fix aufs' permission bug (i.e., upper layer having broader mask than the lower layer). More information about the bug can be found at https://github.com/docker/docker/issues/783 `dirperm1` man page is at: http://aufs.sourceforge.net/aufs3/man.html Signed-off-by: Daniel, Dao Quang Minh (cherry picked from commit 281abd2c8aff542e3b0309eda15536177bcec713) Docker-DCO-1.1-Signed-off-by: Jessie Frazelle (github: jfrazelle) --- daemon/graphdriver/aufs/aufs.go | 46 +++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/daemon/graphdriver/aufs/aufs.go b/daemon/graphdriver/aufs/aufs.go index 60baf0b61..a986fe235 100644 --- a/daemon/graphdriver/aufs/aufs.go +++ b/daemon/graphdriver/aufs/aufs.go @@ -23,6 +23,7 @@ package aufs import ( "bufio" "fmt" + "io/ioutil" "os" "os/exec" "path" @@ -47,6 +48,9 @@ var ( graphdriver.FsMagicAufs, } backingFs = "" + + enableDirpermLock sync.Once + enableDirperm bool ) func init() { @@ -423,7 +427,11 @@ func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err erro // Mount options are clipped to page size(4096 bytes). If there are more // layers then these are remounted individually using append. - b := make([]byte, syscall.Getpagesize()-len(mountLabel)-54) // room for xino & mountLabel + offset := 54 + if useDirperm() { + offset += len("dirperm1") + } + b := make([]byte, syscall.Getpagesize()-len(mountLabel)-offset) // room for xino & mountLabel bp := copy(b, fmt.Sprintf("br:%s=rw", rw)) firstMount := true @@ -447,7 +455,11 @@ func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err erro } if firstMount { - data := label.FormatMountLabel(fmt.Sprintf("%s,dio,xino=/dev/shm/aufs.xino", string(b[:bp])), mountLabel) + opts := "dio,xino=/dev/shm/aufs.xino" + if useDirperm() { + opts += ",dirperm1" + } + data := label.FormatMountLabel(fmt.Sprintf("%s,%s", string(b[:bp]), opts), mountLabel) if err = mount("none", target, "aufs", 0, data); err != nil { return } @@ -461,3 +473,33 @@ func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err erro return } + +// useDirperm checks dirperm1 mount option can be used with the current +// version of aufs. +func useDirperm() bool { + enableDirpermLock.Do(func() { + base, err := ioutil.TempDir("", "docker-aufs-base") + if err != nil { + log.Errorf("error checking dirperm1: %v", err) + return + } + defer os.RemoveAll(base) + + union, err := ioutil.TempDir("", "docker-aufs-union") + if err != nil { + log.Errorf("error checking dirperm1: %v", err) + return + } + defer os.RemoveAll(union) + + opts := fmt.Sprintf("br:%s,dirperm1,xino=/dev/shm/aufs.xino", base) + if err := mount("none", union, "aufs", 0, opts); err != nil { + return + } + enableDirperm = true + if err := Unmount(union); err != nil { + log.Errorf("error checking dirperm1: failed to unmount %v", err) + } + }) + return enableDirperm +}