From e7ba3c61f1055d740539d608cc521d816d07cddd Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 9 Sep 2015 19:32:59 +0200 Subject: [PATCH] Fix File.GettAttr() size reporting The too-large reported value broke mmap (applications saw appended zero bytes) Also * Add locking for all fd operations * Add "--debug" command line switch --- cryptfs/log.go | 12 +++++++++++- main.go | 21 ++++++++++++++++++--- pathfs_frontend/file.go | 6 ++++++ pathfs_frontend/fs.go | 13 +++++++++++-- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/cryptfs/log.go b/cryptfs/log.go index f9c46c8..03d1e29 100644 --- a/cryptfs/log.go +++ b/cryptfs/log.go @@ -2,18 +2,28 @@ package cryptfs import ( "fmt" + "strings" ) type logChannel struct { enabled bool } -func (l logChannel) Printf(format string, args ...interface{}) { +func (l *logChannel) Printf(format string, args ...interface{}) { if l.enabled == true { fmt.Printf(format, args...) } } +func (l *logChannel) Dump(d []byte) { + s := string(d) + fmt.Println(strings.Replace(s, "\000", "\\0", -1)) +} + +func (l *logChannel) Enable() { + l.enabled = true +} + var Debug = logChannel{false} var Warn = logChannel{true} diff --git a/main.go b/main.go index 624b2f5..70f0b53 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "github.com/rfjakob/gocryptfs/cluefs_frontend" "github.com/rfjakob/gocryptfs/pathfs_frontend" + "github.com/rfjakob/gocryptfs/cryptfs" bazilfuse "bazil.org/fuse" bazilfusefs "bazil.org/fuse/fs" @@ -31,11 +32,18 @@ const ( ERREXIT_MOUNT = 3 ERREXIT_SERVE = 4 ERREXIT_MOUNT2 = 5 + ERREXIT_CIPHERDIR = 6 ) func main() { // Parse command line arguments + var debug bool + flag.BoolVar(&debug, "debug", false, "Enable debug output") flag.Parse() + if debug { + cryptfs.Debug.Enable() + cryptfs.Debug.Printf("Debug output enabled\n") + } if flag.NArg() < 2 { fmt.Printf("NArg=%d\n", flag.NArg()) fmt.Printf("usage: %s CIPHERDIR MOUNTPOINT\n", PROGRAM_NAME) @@ -43,13 +51,20 @@ func main() { } cipherdir, _ := filepath.Abs(flag.Arg(0)) mountpoint, _ := filepath.Abs(flag.Arg(1)) + cryptfs.Debug.Printf("cipherdir=%s\nmountpoint=%s\n", cipherdir, mountpoint) + + _, err := os.Stat(cipherdir) + if err != nil { + fmt.Printf("Cipherdir: %s\n", err.Error()) + os.Exit(ERREXIT_CIPHERDIR) + } var key [16]byte if USE_CLUEFS { cluefsFrontend(key, cipherdir, mountpoint) } else { - pathfsFrontend(key, cipherdir, mountpoint) + pathfsFrontend(key, cipherdir, mountpoint, debug) } } @@ -92,7 +107,7 @@ func cluefsFrontend(key [16]byte, cipherdir string, mountpoint string) { os.Exit(0) } -func pathfsFrontend(key [16]byte, cipherdir string, mountpoint string){ +func pathfsFrontend(key [16]byte, cipherdir string, mountpoint string, debug bool){ finalFs := pathfs_frontend.NewFS(key, cipherdir, USE_OPENSSL) @@ -113,7 +128,7 @@ func pathfsFrontend(key [16]byte, cipherdir string, mountpoint string){ fmt.Printf("Mount fail: %v\n", err) os.Exit(1) } - state.SetDebug(PATHFS_DEBUG) + state.SetDebug(debug) fmt.Println("Mounted!") state.Serve() diff --git a/pathfs_frontend/file.go b/pathfs_frontend/file.go index 8fdd4b2..493a223 100644 --- a/pathfs_frontend/file.go +++ b/pathfs_frontend/file.go @@ -58,7 +58,9 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) { alignedOffset, alignedLength, skip := f.cfs.CiphertextRange(off, length) cryptfs.Debug.Printf("CiphertextRange(%d, %d) -> %d, %d, %d\n", off, length, alignedOffset, alignedLength, skip) ciphertext := make([]byte, int(alignedLength)) + f.lock.Lock() n, err := f.fd.ReadAt(ciphertext, int64(alignedOffset)) + f.lock.Unlock() ciphertext = ciphertext[0:n] if err != nil && err != io.EOF { cryptfs.Warn.Printf("read: ReadAt: %s\n", err.Error()) @@ -131,11 +133,14 @@ func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) { blockData = f.cfs.MergeBlocks(oldData, blockData, int(b.Offset)) cryptfs.Debug.Printf("len(oldData)=%d len(blockData)=%d\n", len(oldData), len(blockData)) } + // Write blockOffset, _ := b.CiphertextRange() blockData = f.cfs.EncryptBlock(blockData) cryptfs.Debug.Printf("WriteAt offset=%d length=%d\n", blockOffset, len(blockData)) + f.lock.Lock() _, err := f.fd.WriteAt(blockData, int64(blockOffset)) + f.lock.Unlock() if err != nil { cryptfs.Warn.Printf("Write failed: %s\n", err.Error()) @@ -213,6 +218,7 @@ func (f *file) GetAttr(a *fuse.Attr) fuse.Status { return fuse.ToStatus(err) } a.FromStat(&st) + a.Size = f.cfs.PlainSize(a.Size) return fuse.OK } diff --git a/pathfs_frontend/fs.go b/pathfs_frontend/fs.go index 0c1d879..1e4a1f3 100644 --- a/pathfs_frontend/fs.go +++ b/pathfs_frontend/fs.go @@ -112,8 +112,17 @@ func (fs *FS) Utimens(path string, Atime *time.Time, Mtime *time.Time, context * return fs.FileSystem.Utimens(fs.EncryptPath(path), Atime, Mtime, context) } -func (fs *FS) Readlink(name string, context *fuse.Context) (out string, code fuse.Status) { - return fs.FileSystem.Readlink(fs.EncryptPath(name), context) +func (fs *FS) Readlink(name string, context *fuse.Context) (out string, status fuse.Status) { + dst, status := fs.FileSystem.Readlink(fs.EncryptPath(name), context) + if status != fuse.OK { + return "", status + } + dstPlain, err := fs.DecryptPath(dst) + if err != nil { + cryptfs.Warn.Printf("Failed decrypting symlink: %s\n", err.Error()) + return "", fuse.EIO + } + return dstPlain, status } func (fs *FS) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) (code fuse.Status) {