From d74cf7c72337e7b6d4c57d357e855b19fe1f5c9a Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 8 Mar 2023 16:54:56 +0100 Subject: [PATCH 1/5] speed: add per-blocksize GoGCM benchmarks Only visible when you run "go test -bench" like this: $ cd gocryptfs/internal/speed $ go test -bench . goos: linux goarch: amd64 pkg: github.com/rfjakob/gocryptfs/v2/internal/speed cpu: Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz BenchmarkStupidGCM-4 202352 5937 ns/op 689.96 MB/s BenchmarkStupidGCMDecrypt-4 206023 5782 ns/op 708.38 MB/s BenchmarkGoGCM-4 291878 4098 ns/op 999.45 MB/s BenchmarkGoGCMBlockSize/1024-4 1000000 1151 ns/op 889.88 MB/s BenchmarkGoGCMBlockSize/2048-4 561182 2134 ns/op 959.60 MB/s BenchmarkGoGCMBlockSize/4096-4 292057 4101 ns/op 998.87 MB/s BenchmarkGoGCMBlockSize/8192-4 149216 8031 ns/op 1020.09 MB/s BenchmarkGoGCMBlockSize/16384-4 75361 15917 ns/op 1029.34 MB/s BenchmarkGoGCMBlockSize/32768-4 37916 31649 ns/op 1035.35 MB/s BenchmarkGoGCMBlockSize/65536-4 19005 63117 ns/op 1038.33 MB/s BenchmarkGoGCMBlockSize/131072-4 9498 126166 ns/op 1038.89 MB/s BenchmarkGoGCMBlockSize/262144-4 4755 252149 ns/op 1039.64 MB/s BenchmarkGoGCMBlockSize/524288-4 2377 504108 ns/op 1040.03 MB/s BenchmarkGoGCMBlockSize/1048576-4 1188 1008675 ns/op 1039.56 MB/s BenchmarkGoGCMDecrypt-4 294664 4059 ns/op 1009.02 MB/s BenchmarkAESSIV-4 46498 25432 ns/op 161.05 MB/s BenchmarkAESSIVDecrypt-4 46908 25509 ns/op 160.57 MB/s BenchmarkXchacha-4 244473 4894 ns/op 836.97 MB/s BenchmarkXchachaDecrypt-4 249710 4798 ns/op 853.75 MB/s BenchmarkStupidXchacha-4 166988 7101 ns/op 576.79 MB/s BenchmarkStupidXchachaDecrypt-4 163093 7240 ns/op 565.72 MB/s BenchmarkStupidChacha-4 184172 6527 ns/op 627.58 MB/s BenchmarkStupidChachaDecrypt-4 179796 6659 ns/op 615.11 MB/s PASS ok github.com/rfjakob/gocryptfs/v2/internal/speed 30.068s --- internal/speed/speed.go | 16 ++++++++++++---- internal/speed/speed_test.go | 8 ++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/internal/speed/speed.go b/internal/speed/speed.go index 950bbda..47fe8c9 100644 --- a/internal/speed/speed.go +++ b/internal/speed/speed.go @@ -23,7 +23,7 @@ import ( const adLen = 24 // gocryptfs uses fixed-size 4 kiB blocks -const blockSize = 4096 +const gocryptfsBlockSize = 4096 // Run - run the speed the test and print the results. func Run() { @@ -83,6 +83,11 @@ func randBytes(n int) []byte { // bEncrypt benchmarks the encryption speed of cipher "c" func bEncrypt(b *testing.B, c cipher.AEAD) { + bEncryptBlockSize(b, c, gocryptfsBlockSize) +} + +// bEncryptBlockSize benchmarks the encryption speed of cipher "c" at block size "blockSize" +func bEncryptBlockSize(b *testing.B, c cipher.AEAD, blockSize int) { authData := randBytes(adLen) iv := randBytes(c.NonceSize()) in := make([]byte, blockSize) @@ -97,13 +102,12 @@ func bEncrypt(b *testing.B, c cipher.AEAD) { // Encrypt and append to nonce c.Seal(dst, iv, in, authData) } - } func bDecrypt(b *testing.B, c cipher.AEAD) { authData := randBytes(adLen) iv := randBytes(c.NonceSize()) - plain := randBytes(blockSize) + plain := randBytes(gocryptfsBlockSize) ciphertext := c.Seal(iv, iv, plain, authData) b.SetBytes(int64(len(plain))) @@ -129,6 +133,10 @@ func bStupidGCM(b *testing.B) { // bGoGCM benchmarks Go stdlib GCM func bGoGCM(b *testing.B) { + bGoGCMBlockSize(b, gocryptfsBlockSize) +} + +func bGoGCMBlockSize(b *testing.B, blockSize int) { gAES, err := aes.NewCipher(randBytes(32)) if err != nil { b.Fatal(err) @@ -137,7 +145,7 @@ func bGoGCM(b *testing.B) { if err != nil { b.Fatal(err) } - bEncrypt(b, gGCM) + bEncryptBlockSize(b, gGCM, blockSize) } // bAESSIV benchmarks AES-SIV from github.com/aperturerobotics/jacobsa-crypto/siv diff --git a/internal/speed/speed_test.go b/internal/speed/speed_test.go index 5f3001b..39ef918 100644 --- a/internal/speed/speed_test.go +++ b/internal/speed/speed_test.go @@ -3,6 +3,7 @@ package speed import ( "crypto/aes" "crypto/cipher" + "fmt" "testing" "golang.org/x/crypto/chacha20poly1305" @@ -38,6 +39,13 @@ func BenchmarkGoGCM(b *testing.B) { bGoGCM(b) } +func BenchmarkGoGCMBlockSize(b *testing.B) { + for blockSize := 1024; blockSize <= 1024*1024; blockSize *= 2 { + name := fmt.Sprintf("%d", blockSize) + b.Run(name, func(b *testing.B) { bGoGCMBlockSize(b, blockSize) }) + } +} + func BenchmarkGoGCMDecrypt(b *testing.B) { gAES, err := aes.NewCipher(randBytes(32)) if err != nil { From b370325ccf8a15d3b58418d85fd22e32e2aeb2fc Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 8 Mar 2023 17:04:07 +0100 Subject: [PATCH 2/5] speed: GoGCM: start at block size 16 BenchmarkGoGCMBlockSize/16-4 5499200 219.7 ns/op 72.83 MB/s BenchmarkGoGCMBlockSize/32-4 4497284 266.2 ns/op 120.22 MB/s BenchmarkGoGCMBlockSize/64-4 3296336 363.4 ns/op 176.10 MB/s BenchmarkGoGCMBlockSize/128-4 4204794 285.5 ns/op 448.36 MB/s BenchmarkGoGCMBlockSize/256-4 2928472 409.7 ns/op 624.83 MB/s BenchmarkGoGCMBlockSize/512-4 1825164 658.0 ns/op 778.09 MB/s BenchmarkGoGCMBlockSize/1024-4 1000000 1151 ns/op 889.98 MB/s BenchmarkGoGCMBlockSize/2048-4 560275 2135 ns/op 959.47 MB/s BenchmarkGoGCMBlockSize/4096-4 291906 4099 ns/op 999.28 MB/s BenchmarkGoGCMBlockSize/8192-4 148916 8033 ns/op 1019.83 MB/s BenchmarkGoGCMBlockSize/16384-4 75337 15911 ns/op 1029.75 MB/s BenchmarkGoGCMBlockSize/32768-4 37912 31651 ns/op 1035.30 MB/s BenchmarkGoGCMBlockSize/65536-4 19000 64287 ns/op 1019.43 MB/s BenchmarkGoGCMBlockSize/131072-4 9225 127636 ns/op 1026.92 MB/s BenchmarkGoGCMBlockSize/262144-4 4752 252300 ns/op 1039.02 MB/s BenchmarkGoGCMBlockSize/524288-4 2377 504612 ns/op 1038.99 MB/s BenchmarkGoGCMBlockSize/1048576-4 1183 1011637 ns/op 1036.51 MB/s --- internal/speed/speed_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/speed/speed_test.go b/internal/speed/speed_test.go index 39ef918..0d05081 100644 --- a/internal/speed/speed_test.go +++ b/internal/speed/speed_test.go @@ -40,7 +40,7 @@ func BenchmarkGoGCM(b *testing.B) { } func BenchmarkGoGCMBlockSize(b *testing.B) { - for blockSize := 1024; blockSize <= 1024*1024; blockSize *= 2 { + for blockSize := 16; blockSize <= 1024*1024; blockSize *= 2 { name := fmt.Sprintf("%d", blockSize) b.Run(name, func(b *testing.B) { bGoGCMBlockSize(b, blockSize) }) } From 24b3978715186bed3edc2703e81f165a73c0a74a Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 29 Mar 2023 22:16:14 +0200 Subject: [PATCH 3/5] fusefrontent: report correct size on hard link creation And add a test for it. Fixes https://github.com/rfjakob/gocryptfs/issues/724 --- internal/fusefrontend/node.go | 1 + internal/fusefrontend/node_helpers.go | 1 + tests/matrix/matrix_test.go | 39 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/internal/fusefrontend/node.go b/internal/fusefrontend/node.go index 688cc0d..274123b 100644 --- a/internal/fusefrontend/node.go +++ b/internal/fusefrontend/node.go @@ -334,6 +334,7 @@ func (n *Node) Link(ctx context.Context, target fs.InodeEmbedder, name string, o return } inode = n.newChild(ctx, st, out) + n.translateSize(dirfd, cName, &out.Attr) return inode, 0 } diff --git a/internal/fusefrontend/node_helpers.go b/internal/fusefrontend/node_helpers.go index 46046f1..f5dfeb6 100644 --- a/internal/fusefrontend/node_helpers.go +++ b/internal/fusefrontend/node_helpers.go @@ -62,6 +62,7 @@ func (n *Node) translateSize(dirfd int, cName string, out *fuse.Attr) { rn := n.rootNode() out.Size = rn.contentEnc.CipherSizeToPlainSize(out.Size) } else if out.IsSymlink() { + // read and decrypt target target, _ := n.readlink(dirfd, cName) out.Size = uint64(len(target)) } diff --git a/tests/matrix/matrix_test.go b/tests/matrix/matrix_test.go index 34c111f..0d9c22c 100644 --- a/tests/matrix/matrix_test.go +++ b/tests/matrix/matrix_test.go @@ -915,6 +915,45 @@ func TestSymlinkSize(t *testing.T) { } } +// gocryptfs 2.0+ reported the ciphertext size on hard link creation +// https://github.com/rfjakob/gocryptfs/issues/724 +func TestLinkSize(t *testing.T) { + p := filepath.Join(test_helpers.DefaultPlainDir, t.Name()) + ".regular" + f, err := os.Create(p) + if err != nil { + t.Fatal(err) + } + _, err = f.WriteString("x") + f.Close() + if err != nil { + t.Fatal(err) + } + doTestLinkSize(t, p) + + p = filepath.Join(test_helpers.DefaultPlainDir, t.Name()) + ".symlink" + err = syscall.Symlink("x", p) + if err != nil { + t.Fatal(err) + } + doTestLinkSize(t, p) +} + +func doTestLinkSize(t *testing.T, p string) { + p2 := p + ".link" + err := syscall.Link(p, p2) + if err != nil { + t.Fatal(err) + } + var st syscall.Stat_t + err = syscall.Lstat(p2, &st) + if err != nil { + t.Fatal(filepath.Base(p2), err) + } + if st.Size != 1 { + t.Errorf("wrong %s size: want=1 have=%d", filepath.Base(p), st.Size) + } +} + // TestPwd check that /usr/bin/pwd works inside gocryptfs. // // This was broken in gocryptfs v2.0 with -sharedstorage: From 300fe96ae375d838bab5ad7ef8dc9fc26bc4943c Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sat, 29 Apr 2023 14:35:26 +0200 Subject: [PATCH 4/5] Update go-fuse to v2.3.0 go get github.com/hanwen/go-fuse/v2 --- go.mod | 2 +- go.sum | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 73eabee..d6b0a52 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/aperturerobotics/jacobsa-crypto v1.0.0 - github.com/hanwen/go-fuse/v2 v2.1.1-0.20221117175120-915cf5413cde + github.com/hanwen/go-fuse/v2 v2.3.0 github.com/pkg/xattr v0.4.3 github.com/rfjakob/eme v1.1.2 github.com/sabhiram/go-gitignore v0.0.0-20201211210132-54b8a0bf510f diff --git a/go.sum b/go.sum index ba3cf88..d60d328 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/aperturerobotics/jacobsa-crypto v1.0.0 h1:ARfIuzgovK+5leAKbFHcicKEgMz github.com/aperturerobotics/jacobsa-crypto v1.0.0/go.mod h1:xq0oOkHSPQ1E5ByqbwLhCJ1mygYHtXTMQnvHD4tz4Cc= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/hanwen/go-fuse/v2 v2.1.1-0.20221117175120-915cf5413cde h1:fgTauqHA48CDt+qVQR+PJXqiI9bpYQglMIIi+h/mMts= -github.com/hanwen/go-fuse/v2 v2.1.1-0.20221117175120-915cf5413cde/go.mod h1:B1nGE/6RBFyBRC1RRnf23UpwCdyJ31eukw34oAKukAc= +github.com/hanwen/go-fuse/v2 v2.3.0 h1:t5ivNIH2PK+zw4OBul/iJjsoG9K6kXo4nMDoBpciC8A= +github.com/hanwen/go-fuse/v2 v2.3.0/go.mod h1:xKwi1cF7nXAOBCXujD5ie0ZKsxc8GGSA1rlMJc+8IJs= github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd h1:9GCSedGjMcLZCrusBZuo4tyKLpKUPenUUqi34AkuFmA= github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd/go.mod h1:TlmyIZDpGmwRoTWiakdr+HA1Tukze6C6XbRVidYq02M= github.com/jacobsa/oglemock v0.0.0-20150831005832-e94d794d06ff h1:2xRHTvkpJ5zJmglXLRqHiZQNjUoOkhUyhTAhEQvPAWw= @@ -15,6 +15,8 @@ github.com/jacobsa/reqtrace v0.0.0-20150505043853-245c9e0234cb h1:uSWBjJdMf47kQl github.com/jacobsa/reqtrace v0.0.0-20150505043853-245c9e0234cb/go.mod h1:ivcmUvxXWjb27NsPEaiYK7AidlZXS7oQ5PowUS9z3I4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= +github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/pkg/xattr v0.4.3 h1:5Jx4GCg5ABtqWZH8WLzeI4fOtM1HyX4RBawuCoua1es= github.com/pkg/xattr v0.4.3/go.mod h1:sBD3RAqlr8Q+RC3FutZcikpT8nyDrIEEBw2J744gVWs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -34,7 +36,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0= golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From feb23c5d5893fa3c036beb97434e3b35e9e685a7 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sat, 29 Apr 2023 14:37:52 +0200 Subject: [PATCH 5/5] Update changelog for v2.3.2 --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f19a3e7..6ffa1ff 100644 --- a/README.md +++ b/README.md @@ -195,6 +195,10 @@ RM: 2,367 Changelog --------- +#### v2.3.2, 2023-04-29 +* Fix incorrect file size reported after hard link creation + ([#724](https://github.com/rfjakob/gocryptfs/issues/724)) + #### v2.3.1, 2023-03-04 * Optimize NFS streaming write performance ([#712](https://github.com/rfjakob/gocryptfs/issues/712), [commit](https://github.com/rfjakob/gocryptfs/commit/8f3ec5dcaa6eb18d11746675190a7aaceb422764)).