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 <dqminh89@gmail.com>
This commit is contained in:
parent
f84086be2a
commit
281abd2c8a
1 changed files with 44 additions and 2 deletions
|
@ -23,6 +23,7 @@ package aufs
|
|||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
|
@ -47,6 +48,9 @@ var (
|
|||
graphdriver.FsMagicAufs,
|
||||
}
|
||||
backingFs = "<unknown>"
|
||||
|
||||
enableDirpermLock sync.Once
|
||||
enableDirperm bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -422,7 +426,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
|
||||
|
@ -446,7 +454,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
|
||||
}
|
||||
|
@ -460,3 +472,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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue