diff options
author | Jakob Unterwurzacher | 2024-05-01 22:26:37 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2024-05-01 22:26:37 +0200 |
commit | ed0a12b7337c2d88c027329f64e73070da17d5b3 (patch) | |
tree | 6012eaac28c2b4bc92ff9fb7368eccdba383c0ed /internal/fusefrontend_reverse/root_node.go | |
parent | 210c5c512a7e363d1ada9de2b405463166ec940a (diff) |
reverse: use unique generation number for all nodes
We used to present gocryptfs.longname.*.name files for hardlinked
files as hardlinked to the kernel (same Node ID) which is wrong.
Fix this by using a unique generation number for all nodes, which
also fixes possible issues with inode reuse.
Basically what 1bc1db620b061aabf59469a5eb4fb60e3e1701a3 did
for forward mode with -sharedstorage.
Fixes https://github.com/rfjakob/gocryptfs/issues/802
Diffstat (limited to 'internal/fusefrontend_reverse/root_node.go')
-rw-r--r-- | internal/fusefrontend_reverse/root_node.go | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/internal/fusefrontend_reverse/root_node.go b/internal/fusefrontend_reverse/root_node.go index 8a2afd9..1a68ffd 100644 --- a/internal/fusefrontend_reverse/root_node.go +++ b/internal/fusefrontend_reverse/root_node.go @@ -5,6 +5,7 @@ import ( "os" "path/filepath" "strings" + "sync/atomic" "syscall" "github.com/rfjakob/gocryptfs/v2/internal/exitcodes" @@ -45,6 +46,13 @@ type RootNode struct { // If a file name length is shorter than shortNameMax, there is no need to // hash it. shortNameMax int + // gen is the node generation number. Normally, it is always set to 1, + // but reverse mode, like -sharestorage, uses an incrementing counter for new nodes. + // This makes each directory entry unique (even hard links), + // makes go-fuse hand out separate FUSE Node IDs for each, and prevents + // bizarre problems when inode numbers are reused behind our back, + // like this one: https://github.com/rfjakob/gocryptfs/issues/802 + gen uint64 } // NewRootNode returns an encrypted FUSE overlay filesystem. @@ -149,3 +157,19 @@ func (rn *RootNode) excludeDirEntries(d *dirfdPlus, entries []fuse.DirEntry) (fi } return filtered } + +// uniqueStableAttr returns a fs.StableAttr struct with a unique generation number, +// preventing files to appear hard-linked, even when they have the same inode number. +// +// This is good because inode numbers can be reused behind our back, which could make +// unrelated files appear hard-linked. +// Example: https://github.com/rfjakob/gocryptfs/issues/802 +func (rn *RootNode) uniqueStableAttr(mode uint32, ino uint64) fs.StableAttr { + return fs.StableAttr{ + Mode: mode, + Ino: ino, + // Make each directory entry a unique node by using a unique generation + // value. Also see the comment at RootNode.gen for details. + Gen: atomic.AddUint64(&rn.gen, 1), + } +} |