aboutsummaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse
diff options
context:
space:
mode:
Diffstat (limited to 'internal/fusefrontend_reverse')
-rw-r--r--internal/fusefrontend_reverse/excluder.go18
-rw-r--r--internal/fusefrontend_reverse/excluder_test.go4
-rw-r--r--internal/fusefrontend_reverse/node.go4
-rw-r--r--internal/fusefrontend_reverse/node_dir_ops.go2
-rw-r--r--internal/fusefrontend_reverse/node_helpers.go14
-rw-r--r--internal/fusefrontend_reverse/root_node.go22
-rw-r--r--internal/fusefrontend_reverse/rpath.go4
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)