aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose M Perez2021-08-12 22:48:34 +0200
committerJakob Unterwurzacher2021-08-19 18:05:54 +0200
commit8f94083a2114c3aef4bc0320065e0374c420ea4a (patch)
treed6b56a31e58a99e8a46b4663d6d63b0c3be425b8
parent02c91d73ce2c63f999f2c29cf61d55caef19c67b (diff)
Flag -zerodiriv to create all diriv as all zero byte files
-rw-r--r--Documentation/MANPAGE.md5
-rw-r--r--cli_args.go3
-rw-r--r--init_dir.go2
-rw-r--r--internal/fusefrontend/args.go2
-rw-r--r--internal/fusefrontend/node_dir_ops.go3
-rw-r--r--internal/nametransform/diriv.go16
-rw-r--r--mount.go1
-rw-r--r--tests/test_helpers/helpers.go2
-rw-r--r--tests/zerodiriv/zerodiriv_test.go85
9 files changed, 106 insertions, 13 deletions
diff --git a/Documentation/MANPAGE.md b/Documentation/MANPAGE.md
index 1547591..07f063e 100644
--- a/Documentation/MANPAGE.md
+++ b/Documentation/MANPAGE.md
@@ -545,6 +545,11 @@ useful in regression testing.
Applies to: all actions.
+#### -zerodiriv
+Create diriv as all-zero files
+
+Applies to: all actions without `-plaintextnames`.
+
#### \-\-
Stop option parsing. Helpful when CIPHERDIR may start with a
dash "-".
diff --git a/cli_args.go b/cli_args.go
index 058f932..76e8d30 100644
--- a/cli_args.go
+++ b/cli_args.go
@@ -30,7 +30,7 @@ type argContainer struct {
plaintextnames, quiet, nosyslog, wpanic,
longnames, allow_other, reverse, aessiv, nonempty, raw64,
noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info,
- sharedstorage, devrandom, fsck, one_file_system bool
+ sharedstorage, devrandom, fsck, one_file_system, zerodiriv bool
// Mount options with opposites
dev, nodev, suid, nosuid, exec, noexec, rw, ro, kernel_cache, acl bool
masterkey, mountpoint, cipherdir, cpuprofile,
@@ -179,6 +179,7 @@ func parseCliOpts(osArgs []string) (args argContainer) {
flagSet.BoolVar(&args.devrandom, "devrandom", false, "Use /dev/random for generating master key")
flagSet.BoolVar(&args.fsck, "fsck", false, "Run a filesystem check on CIPHERDIR")
flagSet.BoolVar(&args.one_file_system, "one-file-system", false, "Don't cross filesystem boundaries")
+ flagSet.BoolVar(&args.zerodiriv, "zerodiriv", false, "Create diriv as all-zero files")
// Mount options with opposites
flagSet.BoolVar(&args.dev, "dev", false, "Allow device files")
diff --git a/init_dir.go b/init_dir.go
index 54a44e4..ce5f98d 100644
--- a/init_dir.go
+++ b/init_dir.go
@@ -103,7 +103,7 @@ func initDir(args *argContainer) {
// Open cipherdir (following symlinks)
dirfd, err := syscall.Open(args.cipherdir, syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)
if err == nil {
- err = nametransform.WriteDirIVAt(dirfd)
+ err = nametransform.WriteDirIVAt(dirfd, !args.zerodiriv)
syscall.Close(dirfd)
}
if err != nil {
diff --git a/internal/fusefrontend/args.go b/internal/fusefrontend/args.go
index d92c3ff..02ffddb 100644
--- a/internal/fusefrontend/args.go
+++ b/internal/fusefrontend/args.go
@@ -53,4 +53,6 @@ type Args struct {
// like rsync's `--one-file-system` does.
// Only applicable to reverse mode.
OneFileSystem bool
+ // ZeroDirIV creates diriv files as all-zero files
+ ZeroDirIV bool
}
diff --git a/internal/fusefrontend/node_dir_ops.go b/internal/fusefrontend/node_dir_ops.go
index 6d03544..b43a4e4 100644
--- a/internal/fusefrontend/node_dir_ops.go
+++ b/internal/fusefrontend/node_dir_ops.go
@@ -35,6 +35,7 @@ func haveDsstore(entries []fuse.DirEntry) bool {
// should be a handle to the parent directory, cName is the name of the new
// directory and mode specifies the access permissions to use.
func (n *Node) mkdirWithIv(dirfd int, cName string, mode uint32, context *fuse.Context) error {
+
rn := n.rootNode()
// Between the creation of the directory and the creation of gocryptfs.diriv
// the directory is inconsistent. Take the lock to prevent other readers
@@ -48,7 +49,7 @@ func (n *Node) mkdirWithIv(dirfd int, cName string, mode uint32, context *fuse.C
dirfd2, err := syscallcompat.Openat(dirfd, cName, syscall.O_DIRECTORY|syscall.O_NOFOLLOW|syscallcompat.O_PATH, 0)
if err == nil {
// Create gocryptfs.diriv
- err = nametransform.WriteDirIVAt(dirfd2)
+ err = nametransform.WriteDirIVAt(dirfd2, !rn.args.ZeroDirIV)
syscall.Close(dirfd2)
}
if err != nil {
diff --git a/internal/nametransform/diriv.go b/internal/nametransform/diriv.go
index b10c899..a288aa5 100644
--- a/internal/nametransform/diriv.go
+++ b/internal/nametransform/diriv.go
@@ -1,7 +1,6 @@
package nametransform
import (
- "bytes"
"fmt"
"io"
"os"
@@ -34,9 +33,6 @@ func ReadDirIVAt(dirfd int) (iv []byte, err error) {
return fdReadDirIV(fd)
}
-// allZeroDirIV is preallocated to quickly check if the data read from disk is all zero
-var allZeroDirIV = make([]byte, DirIVLen)
-
// fdReadDirIV reads and verifies the DirIV from an opened gocryptfs.diriv file.
func fdReadDirIV(fd *os.File) (iv []byte, err error) {
// We want to detect if the file is bigger than DirIVLen, so
@@ -50,9 +46,6 @@ func fdReadDirIV(fd *os.File) (iv []byte, err error) {
if len(iv) != DirIVLen {
return nil, fmt.Errorf("wanted %d bytes, got %d", DirIVLen, len(iv))
}
- if bytes.Equal(iv, allZeroDirIV) {
- return nil, fmt.Errorf("diriv is all-zero")
- }
return iv, nil
}
@@ -60,8 +53,13 @@ func fdReadDirIV(fd *os.File) (iv []byte, err error) {
// "dirfd". On error we try to delete the incomplete file.
// This function is exported because it is used from fusefrontend, main,
// and also the automated tests.
-func WriteDirIVAt(dirfd int) error {
- iv := cryptocore.RandBytes(DirIVLen)
+func WriteDirIVAt(dirfd int, randomInitialization bool) error {
+ var iv []byte
+ if randomInitialization {
+ iv = cryptocore.RandBytes(DirIVLen)
+ } else {
+ iv = make([]byte, DirIVLen)
+ }
// 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/commit/7d38f80a78644c8ec4900cc990bfb894387112ed
diff --git a/mount.go b/mount.go
index 8cc038e..64b151b 100644
--- a/mount.go
+++ b/mount.go
@@ -276,6 +276,7 @@ func initFuseFrontend(args *argContainer) (rootNode fs.InodeEmbedder, wipeKeys f
KernelCache: args.kernel_cache,
SharedStorage: args.sharedstorage,
OneFileSystem: args.one_file_system,
+ ZeroDirIV: args.zerodiriv,
}
// confFile is nil when "-zerokey" or "-masterkey" was used
if confFile != nil {
diff --git a/tests/test_helpers/helpers.go b/tests/test_helpers/helpers.go
index 87dba0a..f78c59c 100644
--- a/tests/test_helpers/helpers.go
+++ b/tests/test_helpers/helpers.go
@@ -110,7 +110,7 @@ func ResetTmpDir(createDirIV bool) {
// Open cipherdir (following symlinks)
dirfd, err := syscall.Open(DefaultCipherDir, syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)
if err == nil {
- err = nametransform.WriteDirIVAt(dirfd)
+ err = nametransform.WriteDirIVAt(dirfd, true)
syscall.Close(dirfd)
}
if err != nil {
diff --git a/tests/zerodiriv/zerodiriv_test.go b/tests/zerodiriv/zerodiriv_test.go
new file mode 100644
index 0000000..3fbbf47
--- /dev/null
+++ b/tests/zerodiriv/zerodiriv_test.go
@@ -0,0 +1,85 @@
+package zerodiriv
+
+// integration tests that target zerodiriv specifically
+
+import (
+ "bytes"
+ "path/filepath"
+ "io/ioutil"
+ "os"
+ "testing"
+
+ "github.com/rfjakob/gocryptfs/tests/test_helpers"
+)
+
+var cDir string
+var pDir string
+
+var testPw = []byte("test")
+
+// Create and mount "-zerodiriv" fs
+func TestMain(m *testing.M) {
+ cDir = test_helpers.InitFS(nil, "-zerodiriv")
+ pDir = cDir + ".mnt"
+ test_helpers.MountOrExit(cDir, pDir, "-zerodiriv", "-extpass", "echo test")
+ r := m.Run()
+ test_helpers.UnmountPanic(pDir)
+ os.Exit(r)
+}
+
+// diriv should be all-zero on newly created dirs
+func TestZeroDirIV(t *testing.T) {
+ // Create /dir1, move it and create it again
+ var dirPath = pDir+"/dir1"
+ var err = os.Mkdir(dirPath, 0777)
+ if err != nil {
+ t.Error(err)
+ }
+ err = os.Rename(dirPath, dirPath + ".bak")
+ if err != nil {
+ t.Error(err)
+ }
+ err = os.Mkdir(dirPath, 0777)
+ if err != nil {
+ t.Error(err)
+ }
+
+ var matches []string
+ matches, err = filepath.Glob(cDir+"/*/gocryptfs.diriv")
+ if err != nil {
+ t.Error(err)
+ }
+
+ // The contents of the both diriv files must be the same
+ var diriv0 []byte
+ diriv0, err = ioutil.ReadFile(matches[0])
+ if err != nil {
+ t.Error(err)
+ }
+ var diriv1 []byte
+ diriv1, err = ioutil.ReadFile(matches[1])
+ if err != nil {
+ t.Error(err)
+ }
+ if !bytes.Equal(diriv0, diriv1) {
+ t.Errorf("both dirivs should have the same value")
+ }
+ // And equal to zero
+ zerodiriv := make([]byte, len(diriv0))
+ if !bytes.Equal(diriv0, zerodiriv) {
+ t.Errorf("both dirivs should be all-zero")
+ }
+}
+
+// root diriv should be all-zero
+func TestZeroRootDirIV(t *testing.T) {
+ // The contents of the diriv file must be zero
+ diriv, err := ioutil.ReadFile(cDir+"/gocryptfs.diriv")
+ if err != nil {
+ t.Error(err)
+ }
+ zerodiriv := make([]byte, len(diriv))
+ if !bytes.Equal(diriv, zerodiriv) {
+ t.Errorf("root diriv should be all-zero")
+ }
+}