From 316b916358b8830b53fec9e16b325735aa850b14 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sat, 2 Dec 2017 21:01:47 +0100 Subject: fusefrontend_reverse: secure Open against symlink races ...using the new syscallcompat.OpenNofollow helper. This change secures Open() against symlink race attacks as described in https://github.com/rfjakob/gocryptfs/issues/165 --- internal/fusefrontend_reverse/rfile.go | 14 +++++++++----- internal/fusefrontend_reverse/rfs.go | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/internal/fusefrontend_reverse/rfile.go b/internal/fusefrontend_reverse/rfile.go index 742d697..c10d341 100644 --- a/internal/fusefrontend_reverse/rfile.go +++ b/internal/fusefrontend_reverse/rfile.go @@ -14,6 +14,7 @@ import ( "github.com/rfjakob/gocryptfs/internal/contentenc" "github.com/rfjakob/gocryptfs/internal/pathiv" + "github.com/rfjakob/gocryptfs/internal/syscallcompat" "github.com/rfjakob/gocryptfs/internal/tlog" ) @@ -32,19 +33,22 @@ type reverseFile struct { var inodeTable syncmap.Map -func (rfs *ReverseFS) newFile(relPath string, flags uint32) (nodefs.File, fuse.Status) { - absPath, err := rfs.abs(rfs.decryptPath(relPath)) +// newFile decrypts and opens the path "relPath" and returns a reverseFile +// object. The backing file descriptor is always read-only. +func (rfs *ReverseFS) newFile(relPath string) (*reverseFile, fuse.Status) { + pRelPath, err := rfs.decryptPath(relPath) if err != nil { return nil, fuse.ToStatus(err) } - fd, err := os.OpenFile(absPath, int(flags), 0666) + fd, err := syscallcompat.OpenNofollow(rfs.args.Cipherdir, pRelPath, syscall.O_RDONLY, 0) if err != nil { return nil, fuse.ToStatus(err) } var st syscall.Stat_t - err = syscall.Fstat(int(fd.Fd()), &st) + err = syscall.Fstat(fd, &st) if err != nil { tlog.Warn.Printf("newFile: Fstat error: %v", err) + syscall.Close(fd) return nil, fuse.ToStatus(err) } // See if we have that inode number already in the table @@ -76,7 +80,7 @@ func (rfs *ReverseFS) newFile(relPath string, flags uint32) (nodefs.File, fuse.S } return &reverseFile{ File: nodefs.NewDefaultFile(), - fd: fd, + fd: os.NewFile(uintptr(fd), pRelPath), header: header, block0IV: derivedIVs.Block0IV, contentEnc: rfs.contentEnc, diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go index 8afc270..09ebe9e 100644 --- a/internal/fusefrontend_reverse/rfs.go +++ b/internal/fusefrontend_reverse/rfs.go @@ -218,7 +218,7 @@ func (rfs *ReverseFS) Open(relPath string, flags uint32, context *fuse.Context) if rfs.isNameFile(relPath) { return rfs.newNameFile(relPath) } - return rfs.newFile(relPath, flags) + return rfs.newFile(relPath) } func (rfs *ReverseFS) openDirPlaintextnames(relPath string, entries []fuse.DirEntry) ([]fuse.DirEntry, fuse.Status) { -- cgit v1.2.3