diff options
| author | Jakob Unterwurzacher | 2018-11-04 21:46:51 +0100 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2019-01-01 16:24:25 +0100 | 
| commit | 21f1f858b9bebb20fdb9bb3f99189279bb6c6976 (patch) | |
| tree | 403cdcb41801860000a23d133ce70710acdc78f9 /internal/fusefrontend | |
| parent | de3a2c189578f7636c39fde44fbe1da9c78b367e (diff) | |
fusefrontend: make OpenDir() symlink-safe
Interestingly, little or no performance impact:
$ ./benchmark.bash
Testing gocryptfs at /tmp/benchmark.bash.39W: gocryptfs v1.6-42-g30c2349-dirty; go-fuse v20170619-66-g6df8ddc; 2018-11-04 go1.11
Downloading linux-3.0.tar.gz
/tmp/linux-3.0.tar.gz                  100%[=========================================================================>]  92.20M  2.93MB/s    in 31s
2018-11-04 21:44:44 URL:https://cdn.kernel.org/pub/linux/kernel/v3.0/linux-3.0.tar.gz [96675825/96675825] -> "/tmp/linux-3.0.tar.gz" [1]
WRITE: 262144000 bytes (262 MB, 250 MiB) copied, 1.1808 s, 222 MB/s
READ:  262144000 bytes (262 MB, 250 MiB) copied, 0.866438 s, 303 MB/s
UNTAR: 24.745
MD5:   12.050
LS:    3.525
RM:    9.544
Note: kernel has been updated:
$ uname -a
Linux brikett 4.18.16-200.fc28.x86_64 #1 SMP Sat Oct 20 23:53:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Diffstat (limited to 'internal/fusefrontend')
| -rw-r--r-- | internal/fusefrontend/fs_dir.go | 36 | 
1 files changed, 16 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 | 
