From 7d38f80a78644c8ec4900cc990bfb894387112ed Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sat, 29 Apr 2017 14:15:13 +0200 Subject: [PATCH] nametransform: WriteDirIV: replace ioutil.WriteFile As reported at https://github.com/rfjakob/gocryptfs/issues/105 , the "ioutil.WriteFile(file, iv, 0400)" call causes "permissions denied" errors on an NFSv4 setup. "strace"ing diriv creation and gocryptfs.conf creation shows this: conf (works on the user's NFSv4 mount): openat(AT_FDCWD, "/tmp/a/gocryptfs.conf.tmp", O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0400) = 3 diriv (fails): openat(AT_FDCWD, "/tmp/a/gocryptfs.diriv", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0400) = 3 This patch creates the diriv file with the same flags that are used for creating the conf: openat(AT_FDCWD, "/tmp/a/gocryptfs.diriv", O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0400) = 3 Closes https://github.com/rfjakob/gocryptfs/issues/105 --- internal/nametransform/diriv.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/internal/nametransform/diriv.go b/internal/nametransform/diriv.go index e4670c8..00d059f 100644 --- a/internal/nametransform/diriv.go +++ b/internal/nametransform/diriv.go @@ -2,7 +2,6 @@ package nametransform import ( "io" - "io/ioutil" "os" "path/filepath" "strings" @@ -71,11 +70,24 @@ func fdReadDirIV(fd *os.File) (iv []byte, err error) { func WriteDirIV(dir string) error { iv := cryptocore.RandBytes(DirIVLen) file := filepath.Join(dir, DirIVFilename) - err := ioutil.WriteFile(file, iv, 0400) + // 0400 permissions: gocryptfs.diriv should never be modified after creation. + // Don't use "ioutil.WriteFile", it causes trouble on NFS: https://github.com/rfjakob/gocryptfs/issues/105 + fd, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0400) if err != nil { - tlog.Warn.Printf("WriteDirIV: %v", err) + tlog.Warn.Printf("WriteDirIV: OpenFile: %v", err) + return err } - return err + _, err = fd.Write(iv) + if err != nil { + tlog.Warn.Printf("WriteDirIV: Write: %v", err) + return err + } + err = fd.Close() + if err != nil { + tlog.Warn.Printf("WriteDirIV: Close: %v", err) + return err + } + return nil } // EncryptPathDirIV - encrypt relative plaintext path using EME with DirIV.