diff options
-rw-r--r-- | internal/fusefrontend/fs_dir.go | 36 | ||||
-rw-r--r-- | internal/nametransform/diriv.go | 3 |
2 files changed, 19 insertions, 20 deletions
diff --git a/internal/fusefrontend/fs_dir.go b/internal/fusefrontend/fs_dir.go index 8d27791..9486802 100644 --- a/internal/fusefrontend/fs_dir.go +++ b/internal/fusefrontend/fs_dir.go @@ -260,18 +260,21 @@ retry: return fuse.OK } -// OpenDir implements pathfs.FileSystem +// OpenDir - FUSE call +// +// This function is symlink-safe through use of openBackingDir() and +// ReadDirIVAt(). func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, fuse.Status) { tlog.Debug.Printf("OpenDir(%s)", dirName) - cDirName, err := fs.encryptPath(dirName) + parentDirFd, cDirName, err := fs.openBackingDir(dirName) if err != nil { return nil, fuse.ToStatus(err) } + defer syscall.Close(parentDirFd) // Read ciphertext directory - cDirAbsPath := filepath.Join(fs.args.Cipherdir, cDirName) var cipherEntries []fuse.DirEntry var status fuse.Status - fd, err := syscall.Open(cDirAbsPath, syscall.O_RDONLY|syscall.O_NOFOLLOW, 0) + fd, err := syscallcompat.Openat(parentDirFd, cDirName, syscall.O_RDONLY|syscall.O_NOFOLLOW, 0) if err != nil { return nil, fuse.ToStatus(err) } @@ -283,23 +286,16 @@ func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, f // Get DirIV (stays nil if PlaintextNames is used) var cachedIV []byte if !fs.args.PlaintextNames { - cachedIV, _ = fs.nameTransform.DirIVCache.Lookup(dirName) - if cachedIV == nil { - // Read the DirIV from disk and store it in the cache - fs.dirIVLock.RLock() - cachedIV, err = nametransform.ReadDirIV(cDirAbsPath) - if err != nil { - fs.dirIVLock.RUnlock() - // The directory itself does not exist - if err == syscall.ENOENT { - return nil, fuse.ENOENT - } - // Any other problem warrants an error message - tlog.Warn.Printf("OpenDir %q: could not read gocryptfs.diriv: %v", cDirName, err) - return nil, fuse.EIO + // Read the DirIV from disk + cachedIV, err = nametransform.ReadDirIVAt(fd) + if err != nil { + // The directory itself does not exist + if err == syscall.ENOENT { + return nil, fuse.ENOENT } - fs.nameTransform.DirIVCache.Store(dirName, cachedIV, cDirName) - fs.dirIVLock.RUnlock() + // Any other problem warrants an error message + tlog.Warn.Printf("OpenDir %q: could not read gocryptfs.diriv: %v", cDirName, err) + return nil, fuse.EIO } } // Decrypted directory entries diff --git a/internal/nametransform/diriv.go b/internal/nametransform/diriv.go index c2b9bb1..b98de0c 100644 --- a/internal/nametransform/diriv.go +++ b/internal/nametransform/diriv.go @@ -29,6 +29,9 @@ const ( // This function is exported because it allows for an efficient readdir implementation. // If the directory itself cannot be opened, a syscall error will be returned. // Otherwise, a fmt.Errorf() error value is returned with the details. +// +// TODO: this function is not symlink-safe and should be deleted once the only +// remaining user, EncryptPathDirIV(), is gone. func ReadDirIV(dir string) (iv []byte, err error) { fd, err := os.Open(filepath.Join(dir, DirIVFilename)) if err != nil { |