fusefrontend_reverse: store derived values for hard-linked files
With hard links, the path to a file is not unique. This means that the ciphertext data depends on the path that is used to access the files. Fix that by storing the derived values when we encounter a hard-linked file. This means that the first path wins.
This commit is contained in:
parent
bfc8d47747
commit
9ecf2d1a3f
@ -5,6 +5,10 @@ import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
// In newer Go versions, this has moved to just "sync/syncmap".
|
||||
"golang.org/x/sync/syncmap"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
@ -26,6 +30,13 @@ type reverseFile struct {
|
||||
contentEnc *contentenc.ContentEnc
|
||||
}
|
||||
|
||||
var inodeTable syncmap.Map
|
||||
|
||||
type derivedIVContainer struct {
|
||||
id []byte
|
||||
block0IV []byte
|
||||
}
|
||||
|
||||
func (rfs *ReverseFS) newFile(relPath string, flags uint32) (nodefs.File, fuse.Status) {
|
||||
absPath, err := rfs.abs(rfs.decryptPath(relPath))
|
||||
if err != nil {
|
||||
@ -35,16 +46,45 @@ func (rfs *ReverseFS) newFile(relPath string, flags uint32) (nodefs.File, fuse.S
|
||||
if err != nil {
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
id := derivePathIV(relPath, ivPurposeFileID)
|
||||
var st syscall.Stat_t
|
||||
err = syscall.Fstat(int(fd.Fd()), &st)
|
||||
if err != nil {
|
||||
tlog.Warn.Printf("newFile: Fstat error: %v", err)
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
// See if we have that inode number already in the table
|
||||
// (even if Nlink has dropped to 1)
|
||||
var derivedIVs derivedIVContainer
|
||||
v, found := inodeTable.Load(st.Ino)
|
||||
if found {
|
||||
tlog.Debug.Printf("ino%d: newFile: found in the inode table", st.Ino)
|
||||
derivedIVs = v.(derivedIVContainer)
|
||||
} else {
|
||||
derivedIVs.id = derivePathIV(relPath, ivPurposeFileID)
|
||||
derivedIVs.block0IV = derivePathIV(relPath, ivPurposeBlock0IV)
|
||||
// Nlink > 1 means there is more than one path to this file.
|
||||
// Store the derived values so we always return the same data,
|
||||
// regardless of the path that is used to access the file.
|
||||
// This means that the first path wins.
|
||||
if st.Nlink > 1 {
|
||||
v, found = inodeTable.LoadOrStore(st.Ino, derivedIVs)
|
||||
if found {
|
||||
// Another thread has stored a different value before we could.
|
||||
derivedIVs = v.(derivedIVContainer)
|
||||
} else {
|
||||
tlog.Debug.Printf("ino%d: newFile: Nlink=%d, stored in the inode table", st.Ino, st.Nlink)
|
||||
}
|
||||
}
|
||||
}
|
||||
header := contentenc.FileHeader{
|
||||
Version: contentenc.CurrentVersion,
|
||||
ID: id,
|
||||
ID: derivedIVs.id,
|
||||
}
|
||||
return &reverseFile{
|
||||
File: nodefs.NewDefaultFile(),
|
||||
fd: fd,
|
||||
header: header,
|
||||
block0IV: derivePathIV(relPath, ivPurposeBlock0IV),
|
||||
block0IV: derivedIVs.block0IV,
|
||||
contentEnc: rfs.contentEnc,
|
||||
}, fuse.OK
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user