aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2017-11-26 21:27:29 +0100
committerJakob Unterwurzacher2017-11-26 21:37:12 +0100
commit1bb47b6796c7a2cfb64e6cdff37c43c03c473a81 (patch)
treeb223c301a1b95506f20f876b13b2145d7a0f113b
parent90687215a42b2e074f3b5a85cf344ca998fa34ac (diff)
reverse: reject too-long symlink target reads with ENAMETOOLONG
If the symlink target gets too long due to base64 encoding, we should return ENAMETOOLONG instead of having the kernel reject the data and returning an I/O error to the user. Fixes https://github.com/rfjakob/gocryptfs/issues/167
-rw-r--r--internal/fusefrontend_reverse/rfs.go6
-rw-r--r--tests/reverse/correctness_test.go22
2 files changed, 28 insertions, 0 deletions
diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go
index 53e6d22..8afc270 100644
--- a/internal/fusefrontend_reverse/rfs.go
+++ b/internal/fusefrontend_reverse/rfs.go
@@ -319,5 +319,11 @@ func (rfs *ReverseFS) Readlink(cipherPath string, context *fuse.Context) (string
// Symlinks are encrypted like file contents and base64-encoded
cBinTarget := rfs.contentEnc.EncryptBlockNonce([]byte(plainTarget), 0, nil, nonce)
cTarget := rfs.nameTransform.B64.EncodeToString(cBinTarget)
+ // The kernel will reject a symlink target above 4096 chars and return
+ // and I/O error to the user. Better emit the proper error ourselves.
+ const PATH_MAX = 4096 // not defined on Darwin
+ if len(cTarget) > PATH_MAX {
+ return "", fuse.Status(syscall.ENAMETOOLONG)
+ }
return cTarget, fuse.OK
}
diff --git a/tests/reverse/correctness_test.go b/tests/reverse/correctness_test.go
index ee0a5b0..63043b7 100644
--- a/tests/reverse/correctness_test.go
+++ b/tests/reverse/correctness_test.go
@@ -147,3 +147,25 @@ func TestEnoent(t *testing.T) {
t.Errorf("want ENOENT, got: %v", err)
}
}
+
+// If the symlink target gets too long due to base64 encoding, we should
+// return ENAMETOOLONG instead of having the kernel reject the data and
+// returning an I/O error to the user.
+// https://github.com/rfjakob/gocryptfs/issues/167
+func TestTooLongSymlink(t *testing.T) {
+ fn := dirA + "/TooLongSymlink"
+ target := string(bytes.Repeat([]byte("x"), 4000))
+ err := os.Symlink(target, fn)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = os.Readlink(dirC + "/TooLongSymlink")
+ if err == nil {
+ return
+ }
+ err2 := err.(*os.PathError)
+ if err2.Err != syscall.ENAMETOOLONG {
+ t.Errorf("Expected %q error, got %q instead", syscall.ENAMETOOLONG,
+ err2.Err)
+ }
+}