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 | |
parent | 8372f8b94769827c2055195f59f7ea277e3aef9f (diff) |
fusefrontend_reverse: switch from sabhiram/go-gitignore to internal/go-git-gitignore
-rw-r--r-- | go.mod | 1 | ||||
-rw-r--r-- | go.sum | 12 | ||||
-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 |
9 files changed, 43 insertions, 38 deletions
@@ -8,7 +8,6 @@ require ( github.com/moby/sys/mountinfo v0.7.2 github.com/pkg/xattr v0.4.9 github.com/rfjakob/eme v1.1.2 - github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 github.com/spf13/pflag v1.0.5 golang.org/x/crypto v0.33.0 golang.org/x/sys v0.30.0 @@ -1,7 +1,5 @@ github.com/aperturerobotics/jacobsa-crypto v1.1.0 h1:0hig54FMzU80OHrqSfqmj/W8HydRymVdz2K6D9Guffs= github.com/aperturerobotics/jacobsa-crypto v1.1.0/go.mod h1:buWU1iY+FjIcfpb1aYfFJZfl07WlS7O30lTyC2iwjv8= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/hanwen/go-fuse/v2 v2.7.3-0.20250306214706-e3463465126a h1:Q+A/Qcj02oRubB/7+18SGNxAG/GtnoXxf0UKRJ2/ZE4= github.com/hanwen/go-fuse/v2 v2.7.3-0.20250306214706-e3463465126a/go.mod h1:yE6D2PqWwm3CbYRxFXV9xUd8Md5d6NG0WBs5spCswmI= github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd h1:9GCSedGjMcLZCrusBZuo4tyKLpKUPenUUqi34AkuFmA= @@ -13,17 +11,10 @@ github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9Kou github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/pkg/xattr v0.4.9 h1:5883YPCtkSd8LFbs13nXplj9g9tlrwoJRjgpgMu1/fE= github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rfjakob/eme v1.1.2 h1:SxziR8msSOElPayZNFfQw4Tjx/Sbaeeh3eRvrHVMUs4= github.com/rfjakob/eme v1.1.2/go.mod h1:cVvpasglm/G3ngEfcfT/Wt0GwhkuO32pf/poW6Nyk1k= -github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= -github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= @@ -32,6 +23,3 @@ golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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) |