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
This commit is contained in:
Jakob Unterwurzacher 2017-11-26 21:27:29 +01:00
parent 90687215a4
commit 1bb47b6796
2 changed files with 28 additions and 0 deletions

View File

@ -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
}

View File

@ -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)
}
}