aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/fusefrontend/fs_dir.go36
-rw-r--r--internal/nametransform/diriv.go3
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 {