From ed0a12b7337c2d88c027329f64e73070da17d5b3 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 1 May 2024 22:26:37 +0200 Subject: 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 --- internal/fusefrontend_reverse/root_node.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'internal/fusefrontend_reverse/root_node.go') 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), + } +} -- cgit v1.2.3