summaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse/node_helpers.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/fusefrontend_reverse/node_helpers.go')
-rw-r--r--internal/fusefrontend_reverse/node_helpers.go51
1 files changed, 38 insertions, 13 deletions
diff --git a/internal/fusefrontend_reverse/node_helpers.go b/internal/fusefrontend_reverse/node_helpers.go
index 76ddd42..92f6a87 100644
--- a/internal/fusefrontend_reverse/node_helpers.go
+++ b/internal/fusefrontend_reverse/node_helpers.go
@@ -47,6 +47,20 @@ func (n *Node) rootNode() *RootNode {
return n.Root().Operations().(*RootNode)
}
+// dirfdPlus gets filled out as we gather information about a node
+type dirfdPlus struct {
+ // fd to the directory, opened with O_DIRECTORY|O_PATH
+ dirfd int
+ // Relative plaintext path
+ pPath string
+ // Plaintext basename: filepath.Base(pPath)
+ pName string
+ // Relative ciphertext path
+ cPath string
+ // Ciphertext basename: filepath.Base(cPath)
+ cName string
+}
+
// prepareAtSyscall returns a (dirfd, cName) pair that can be used
// with the "___at" family of system calls (openat, fstatat, unlinkat...) to
// access the backing encrypted directory.
@@ -54,16 +68,23 @@ func (n *Node) rootNode() *RootNode {
// If you pass a `child` file name, the (dirfd, cName) pair will refer to
// a child of this node.
// If `child` is empty, the (dirfd, cName) pair refers to this node itself.
-func (n *Node) prepareAtSyscall(child string) (dirfd int, pName string, errno syscall.Errno) {
- p := n.Path()
+func (n *Node) prepareAtSyscall(child string) (d *dirfdPlus, errno syscall.Errno) {
+ cPath := n.Path()
if child != "" {
- p = filepath.Join(p, child)
+ cPath = filepath.Join(cPath, child)
}
rn := n.rootNode()
- dirfd, pName, err := rn.openBackingDir(p)
+ dirfd, pPath, err := rn.openBackingDir(cPath)
if err != nil {
errno = fs.ToErrno(err)
}
+ d = &dirfdPlus{
+ dirfd: dirfd,
+ pPath: pPath,
+ pName: filepath.Base(pPath),
+ cPath: cPath,
+ cName: filepath.Base(cPath),
+ }
return
}
@@ -91,28 +112,32 @@ func (n *Node) isRoot() bool {
}
func (n *Node) lookupLongnameName(ctx context.Context, nameFile string, out *fuse.EntryOut) (ch *fs.Inode, errno syscall.Errno) {
- dirfd, pName1, errno := n.prepareAtSyscall("")
+ d, errno := n.prepareAtSyscall("")
if errno != 0 {
return
}
- defer syscall.Close(dirfd)
+ defer syscall.Close(d.dirfd)
// Find the file the gocryptfs.longname.XYZ.name file belongs to in the
// directory listing
- fd, err := syscallcompat.Openat(dirfd, pName1, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0)
+ fd, err := syscallcompat.Openat(d.dirfd, d.pName, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0)
if err != nil {
errno = fs.ToErrno(err)
return
}
defer syscall.Close(fd)
- diriv := pathiv.Derive(n.Path(), pathiv.PurposeDirIV)
+ diriv := pathiv.Derive(d.cPath, pathiv.PurposeDirIV)
rn := n.rootNode()
pName, cFullname, errno := rn.findLongnameParent(fd, diriv, nameFile)
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(dirfd, pName, unix.AT_SYMLINK_NOFOLLOW)
+ st, err := syscallcompat.Fstatat2(fd, pName, unix.AT_SYMLINK_NOFOLLOW)
if err != nil {
errno = fs.ToErrno(err)
return
@@ -132,17 +157,17 @@ func (n *Node) lookupLongnameName(ctx context.Context, nameFile string, out *fus
// lookupDiriv returns a new Inode for a gocryptfs.diriv file inside `n`.
func (n *Node) lookupDiriv(ctx context.Context, out *fuse.EntryOut) (ch *fs.Inode, errno syscall.Errno) {
- dirfd, pName, errno := n.prepareAtSyscall("")
+ d, errno := n.prepareAtSyscall("")
if errno != 0 {
return
}
- defer syscall.Close(dirfd)
- st, err := syscallcompat.Fstatat2(dirfd, pName, unix.AT_SYMLINK_NOFOLLOW)
+ defer syscall.Close(d.dirfd)
+ st, err := syscallcompat.Fstatat2(d.dirfd, d.pName, unix.AT_SYMLINK_NOFOLLOW)
if err != nil {
errno = fs.ToErrno(err)
return
}
- content := pathiv.Derive(n.Path(), pathiv.PurposeDirIV)
+ content := pathiv.Derive(d.cPath, pathiv.PurposeDirIV)
var vf *VirtualMemNode
vf, errno = n.newVirtualMemNode(content, st, inoTagDirIV)
if errno != 0 {