syscallcompat: use O_PATH in OpenDirNofollow
This fixes the "0100 directory" problem in reverse mode, and should be slightly faster.
This commit is contained in:
parent
9ec9d0c49c
commit
930c37e03d
@ -63,9 +63,15 @@ func (rfs *ReverseFS) findLongnameParent(dir string, dirIV []byte, longname stri
|
||||
if hit != "" {
|
||||
return hit, nil
|
||||
}
|
||||
fd, err := syscallcompat.OpenDirNofollow(rfs.args.Cipherdir, dir)
|
||||
dirfd, err := syscallcompat.OpenDirNofollow(rfs.args.Cipherdir, filepath.Dir(dir))
|
||||
if err != nil {
|
||||
tlog.Warn.Printf("findLongnameParent: opendir failed: %v\n", err)
|
||||
tlog.Warn.Printf("findLongnameParent: OpenDirNofollow failed: %v\n", err)
|
||||
return "", err
|
||||
}
|
||||
fd, err := syscallcompat.Openat(dirfd, filepath.Base(dir), syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0)
|
||||
syscall.Close(dirfd)
|
||||
if err != nil {
|
||||
tlog.Warn.Printf("findLongnameParent: Openat failed: %v\n", err)
|
||||
return "", err
|
||||
}
|
||||
dirEntries, err := syscallcompat.Getdents(fd)
|
||||
|
@ -305,7 +305,12 @@ func (rfs *ReverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse.
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
// Read plaintext dir
|
||||
fd, err := syscallcompat.OpenDirNofollow(rfs.args.Cipherdir, relPath)
|
||||
dirfd, err := syscallcompat.OpenDirNofollow(rfs.args.Cipherdir, filepath.Dir(relPath))
|
||||
if err != nil {
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
fd, err := syscallcompat.Openat(dirfd, filepath.Base(relPath), syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0)
|
||||
syscall.Close(dirfd)
|
||||
if err != nil {
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ func OpenDirNofollow(baseDir string, relPath string) (fd int, err error) {
|
||||
// Walk the directory tree
|
||||
var dirfd2 int
|
||||
for _, name := range parts {
|
||||
dirfd2, err = Openat(dirfd, name, syscall.O_RDONLY|syscall.O_NOFOLLOW|syscall.O_DIRECTORY, 0)
|
||||
dirfd2, err = Openat(dirfd, name, syscall.O_RDONLY|syscall.O_NOFOLLOW|syscall.O_DIRECTORY|O_PATH, 0)
|
||||
syscall.Close(dirfd)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
|
@ -9,9 +9,14 @@ import (
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// O_DIRECT means oncached I/O on Linux. No direct equivalent on MacOS and defined
|
||||
// to zero there.
|
||||
const O_DIRECT = 0
|
||||
const (
|
||||
// O_DIRECT means oncached I/O on Linux. No direct equivalent on MacOS and defined
|
||||
// to zero there.
|
||||
O_DIRECT = 0
|
||||
|
||||
// O_PATH is only defined on Linux
|
||||
O_PATH = 0
|
||||
)
|
||||
|
||||
// Sorry, fallocate is not available on OSX at all and
|
||||
// fcntl F_PREALLOCATE is not accessible from Go.
|
||||
|
@ -12,11 +12,16 @@ import (
|
||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||
)
|
||||
|
||||
const _FALLOC_FL_KEEP_SIZE = 0x01
|
||||
const (
|
||||
_FALLOC_FL_KEEP_SIZE = 0x01
|
||||
|
||||
// O_DIRECT means oncached I/O on Linux. No direct equivalent on MacOS and defined
|
||||
// to zero there.
|
||||
const O_DIRECT = syscall.O_DIRECT
|
||||
// O_DIRECT means oncached I/O on Linux. No direct equivalent on MacOS and defined
|
||||
// to zero there.
|
||||
O_DIRECT = syscall.O_DIRECT
|
||||
|
||||
// O_PATH is only defined on Linux
|
||||
O_PATH = unix.O_PATH
|
||||
)
|
||||
|
||||
var preallocWarn sync.Once
|
||||
|
||||
|
@ -207,3 +207,33 @@ func TestTooLongSymlink(t *testing.T) {
|
||||
err2.Err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test that we can traverse a directory with 0100 permissions
|
||||
// (execute but no read). This used to be a problem as OpenDirNofollow opened
|
||||
// all directory in the path with O_RDONLY. Now it uses O_PATH, which only needs
|
||||
// the executable bit.
|
||||
func Test0100Dir(t *testing.T) {
|
||||
dir := dirA + "/" + t.Name()
|
||||
err := os.Mkdir(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
file := dir + "/hello"
|
||||
err = ioutil.WriteFile(file, []byte("hello"), 0600)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = os.Chmod(dir, 0100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fileReverse := dirC + "/" + t.Name() + "/hello"
|
||||
fd, err := os.Open(fileReverse)
|
||||
// Make sure the dir can be removed after the test is done
|
||||
os.Chmod(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fd.Close()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user