summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)
+ }
+}