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 { | 
