aboutsummaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse/root_node.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2024-05-01 22:26:37 +0200
committerJakob Unterwurzacher2024-05-01 22:26:37 +0200
commited0a12b7337c2d88c027329f64e73070da17d5b3 (patch)
tree6012eaac28c2b4bc92ff9fb7368eccdba383c0ed /internal/fusefrontend_reverse/root_node.go
parent210c5c512a7e363d1ada9de2b405463166ec940a (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.go24
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),
+ }
+}