diff options
author | Jakob Unterwurzacher | 2025-06-28 16:22:29 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2025-07-09 19:28:09 +0200 |
commit | b499c26526ff3a257310ed9fc2c04680d3ee4ab6 (patch) | |
tree | b2a8408eaf40f6ed94e18a36d29a03d43d8b9715 /internal | |
parent | 8372f8b94769827c2055195f59f7ea277e3aef9f (diff) |
fusefrontend_reverse: switch from sabhiram/go-gitignore to internal/go-git-gitignore
Diffstat (limited to 'internal')
-rw-r--r-- | internal/fusefrontend_reverse/excluder.go | 18 | ||||
-rw-r--r-- | internal/fusefrontend_reverse/excluder_test.go | 4 | ||||
-rw-r--r-- | internal/fusefrontend_reverse/node.go | 4 | ||||
-rw-r--r-- | internal/fusefrontend_reverse/node_dir_ops.go | 2 | ||||
-rw-r--r-- | internal/fusefrontend_reverse/node_helpers.go | 14 | ||||
-rw-r--r-- | internal/fusefrontend_reverse/root_node.go | 22 | ||||
-rw-r--r-- | internal/fusefrontend_reverse/rpath.go | 4 |
7 files changed, 43 insertions, 25 deletions
diff --git a/internal/fusefrontend_reverse/excluder.go b/internal/fusefrontend_reverse/excluder.go index 1cb4b80..4ee9daf 100644 --- a/internal/fusefrontend_reverse/excluder.go +++ b/internal/fusefrontend_reverse/excluder.go @@ -9,17 +9,23 @@ import ( "github.com/rfjakob/gocryptfs/v2/internal/fusefrontend" "github.com/rfjakob/gocryptfs/v2/internal/tlog" - "github.com/sabhiram/go-gitignore" + gitignore "github.com/rfjakob/gocryptfs/v2/internal/go-git-gitignore" ) // prepareExcluder creates an object to check if paths are excluded // based on the patterns specified in the command line. -func prepareExcluder(args fusefrontend.Args) *ignore.GitIgnore { - patterns := getExclusionPatterns(args) - if len(patterns) == 0 { - log.Panic(patterns) +func prepareExcluder(args fusefrontend.Args) gitignore.Matcher { + lines := getExclusionPatterns(args) + if len(lines) == 0 { + log.Panic(lines) } - return ignore.CompileIgnoreLines(patterns...) + + var patterns []gitignore.Pattern + for _, l := range lines { + patterns = append(patterns, gitignore.ParsePattern(l, nil)) + } + + return gitignore.NewMatcher(patterns) } // getExclusionPatters prepares a list of patterns to be excluded. diff --git a/internal/fusefrontend_reverse/excluder_test.go b/internal/fusefrontend_reverse/excluder_test.go index b44ddce..4888c85 100644 --- a/internal/fusefrontend_reverse/excluder_test.go +++ b/internal/fusefrontend_reverse/excluder_test.go @@ -3,6 +3,7 @@ package fusefrontend_reverse import ( "os" "reflect" + "syscall" "testing" "github.com/rfjakob/gocryptfs/v2/internal/fusefrontend" @@ -59,7 +60,8 @@ func TestShouldReadExcludePatternsFromFiles(t *testing.T) { func TestShouldReturnFalseIfThereAreNoExclusions(t *testing.T) { var rfs RootNode - if rfs.isExcludedPlain("any/path") { + if rfs.isExcludedMode("any/path", syscall.S_IFREG) { t.Error("Should not exclude any path if no exclusions were specified") + // Also should not panic } } diff --git a/internal/fusefrontend_reverse/node.go b/internal/fusefrontend_reverse/node.go index 30654e0..a78c116 100644 --- a/internal/fusefrontend_reverse/node.go +++ b/internal/fusefrontend_reverse/node.go @@ -62,6 +62,10 @@ func (n *Node) Lookup(ctx context.Context, cName string, out *fuse.EntryOut) (ch if err != nil { return nil, fs.ToErrno(err) } + if rn.isExcludedMode(d.pPath, st.Mode) { + tlog.Debug.Printf("Lookup: %q is excluded. Returning EPERM.", d.cPath) + return nil, syscall.EPERM + } // Create new inode and fill `out` ch = n.newChild(ctx, st, out) // Translate ciphertext size in `out.Attr.Size` to plaintext size diff --git a/internal/fusefrontend_reverse/node_dir_ops.go b/internal/fusefrontend_reverse/node_dir_ops.go index fdd15ce..a63c202 100644 --- a/internal/fusefrontend_reverse/node_dir_ops.go +++ b/internal/fusefrontend_reverse/node_dir_ops.go @@ -59,8 +59,8 @@ func (n *Node) Readdir(ctx context.Context) (stream fs.DirStream, errno syscall. return n.readdirPlaintextnames(entries) } - dirIV := rn.deriveDirIV(d.cPath) // Encrypt names + dirIV := rn.deriveDirIV(d.cPath) for i := range entries { var cName string // ".gocryptfs.reverse.conf" in the root directory is mapped to "gocryptfs.conf" diff --git a/internal/fusefrontend_reverse/node_helpers.go b/internal/fusefrontend_reverse/node_helpers.go index 3165db6..9fb16b8 100644 --- a/internal/fusefrontend_reverse/node_helpers.go +++ b/internal/fusefrontend_reverse/node_helpers.go @@ -14,6 +14,7 @@ import ( "github.com/rfjakob/gocryptfs/v2/internal/configfile" "github.com/rfjakob/gocryptfs/v2/internal/pathiv" "github.com/rfjakob/gocryptfs/v2/internal/syscallcompat" + "github.com/rfjakob/gocryptfs/v2/internal/tlog" ) const ( @@ -113,6 +114,7 @@ func (n *Node) isRoot() bool { return &rn.Node == n } +// lookupLongnameName is called by Lookup for gocryptfs.longname.XYZ.name files func (n *Node) lookupLongnameName(ctx context.Context, nameFile string, out *fuse.EntryOut) (ch *fs.Inode, errno syscall.Errno) { d, errno := n.prepareAtSyscall("") if errno != 0 { @@ -134,16 +136,16 @@ func (n *Node) lookupLongnameName(ctx context.Context, nameFile string, out *fus if errno != 0 { return } - if rn.isExcludedPlain(filepath.Join(d.cPath, pName)) { - errno = syscall.EPERM - return - } // Get attrs from parent file st, err := syscallcompat.Fstatat2(fd, pName, unix.AT_SYMLINK_NOFOLLOW) if err != nil { errno = fs.ToErrno(err) return } + if rn.isExcludedMode(filepath.Join(d.pPath, pName), st.Mode) { + tlog.Debug.Printf("lookupLongnameName: %q is excluded. Returning EPERM.", d.cPath) + return nil, syscall.EPERM + } var vf *VirtualMemNode vf, errno = n.newVirtualMemNode([]byte(cFullname), st, inoTagNameFile) if errno != 0 { @@ -190,6 +192,10 @@ func (n *Node) lookupDiriv(ctx context.Context, out *fuse.EntryOut) (ch *fs.Inod // lookupConf returns a new Inode for the gocryptfs.conf file func (n *Node) lookupConf(ctx context.Context, out *fuse.EntryOut) (ch *fs.Inode, errno syscall.Errno) { rn := n.rootNode() + if rn.isExcludedMode(configfile.ConfReverseName, syscall.S_IFREG) { + tlog.Debug.Printf("lookupConf: file %q is excluded. Returning EPERM.", configfile.ConfDefaultName) + return nil, syscall.EPERM + } p := filepath.Join(rn.args.Cipherdir, configfile.ConfReverseName) var st syscall.Stat_t err := syscall.Stat(p, &st) diff --git a/internal/fusefrontend_reverse/root_node.go b/internal/fusefrontend_reverse/root_node.go index 9c2de28..9f4040d 100644 --- a/internal/fusefrontend_reverse/root_node.go +++ b/internal/fusefrontend_reverse/root_node.go @@ -16,12 +16,11 @@ import ( "github.com/rfjakob/gocryptfs/v2/internal/contentenc" "github.com/rfjakob/gocryptfs/v2/internal/exitcodes" "github.com/rfjakob/gocryptfs/v2/internal/fusefrontend" + gitignore "github.com/rfjakob/gocryptfs/v2/internal/go-git-gitignore" "github.com/rfjakob/gocryptfs/v2/internal/inomap" "github.com/rfjakob/gocryptfs/v2/internal/nametransform" "github.com/rfjakob/gocryptfs/v2/internal/syscallcompat" "github.com/rfjakob/gocryptfs/v2/internal/tlog" - - ignore "github.com/sabhiram/go-gitignore" ) // RootNode is the root directory in a `gocryptfs -reverse` mount @@ -34,7 +33,7 @@ type RootNode struct { // Content encryption helper contentEnc *contentenc.ContentEnc // Tests whether a path is excluded (hidden) from the user. Used by -exclude. - excluder ignore.IgnoreParser + excluder gitignore.Matcher // inoMap translates inode numbers from different devices to unique inode // numbers. inoMap *inomap.InoMap @@ -132,14 +131,18 @@ func (rn *RootNode) findLongnameParent(fd int, diriv []byte, longname string) (p return } -// isExcludedPlain finds out if the plaintext path "pPath" is -// excluded (used when -exclude is passed by the user). -func (rn *RootNode) isExcludedPlain(pPath string) bool { +// isExcludedSt finds out if the plaintext path "pPath" with the stat result +// "st.Mode" is excluded (used when -exclude is passed by the user). +func (rn *RootNode) isExcludedMode(pPath string, mode uint32) bool { // root dir can't be excluded if pPath == "" { return false } - return rn.excluder != nil && rn.excluder.MatchesPath(pPath) + if rn.excluder == nil { + return false + } + isDir := mode&syscall.S_IFDIR != 0 + return rn.excluder.Match(strings.Split(pPath, "/"), isDir) } // excludeDirEntries filters out directory entries that are "-exclude"d. @@ -154,8 +157,9 @@ func (rn *RootNode) excludeDirEntries(d *dirfdPlus, entries []fuse.DirEntry) (fi // filepath.Join handles the case of pDir="" correctly: // Join("", "foo") -> "foo". This does not: pDir + "/" + name" p := filepath.Join(d.pPath, entry.Name) - if rn.isExcludedPlain(p) { - // Skip file + if rn.isExcludedMode(p, entry.Mode) { + // Skip file, and don't leak the plaintext name in the logs. + tlog.Debug.Printf("excludeDirEntries: ino%d is excluded. Skipping.", entry.Ino) continue } filtered = append(filtered, entry) diff --git a/internal/fusefrontend_reverse/rpath.go b/internal/fusefrontend_reverse/rpath.go index 9625dc2..39857ff 100644 --- a/internal/fusefrontend_reverse/rpath.go +++ b/internal/fusefrontend_reverse/rpath.go @@ -109,10 +109,6 @@ func (rn *RootNode) openBackingDir(cPath string) (dirfd int, pPath string, err e if err != nil { return } - if rn.isExcludedPlain(pPath) { - err = syscall.EPERM - return - } // Open directory, safe against symlink races pDir := filepath.Dir(pPath) dirfd, err = syscallcompat.OpenDirNofollow(rn.args.Cipherdir, pDir) |