From 3009ec9852316c3c696f77f476390ab5a6d8d6d7 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Tue, 17 Oct 2017 21:47:32 +0200 Subject: fusefrontend: clamp oversized reads Our byte cache pools are sized acc. to MAX_KERNEL_WRITE, but the running kernel may have a higher limit set. Clamp to what we can handle. Fixes a panic on a Synology NAS reported at https://github.com/rfjakob/gocryptfs/issues/145 --- internal/fusefrontend/file.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'internal/fusefrontend/file.go') diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go index 30e6e3d..be15280 100644 --- a/internal/fusefrontend/file.go +++ b/internal/fusefrontend/file.go @@ -132,6 +132,8 @@ func (f *file) createHeader() (fileID []byte, err error) { return h.ID, err } +var oversizedReadWarn sync.Once + // doRead - read "length" plaintext bytes from plaintext offset "off" and append // to "dst". // Arguments "length" and "off" do not have to be block-aligned. @@ -142,6 +144,16 @@ func (f *file) createHeader() (fileID []byte, err error) { // Called by Read() for normal reading, // by Write() and Truncate() for Read-Modify-Write func (f *file) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Status) { + // Our byte cache pools are sized acc. to MAX_KERNEL_WRITE, but the + // running kernel may have a higher limit set. Clamp to what we can + // handle. + if length > fuse.MAX_KERNEL_WRITE { + oversizedReadWarn.Do(func() { + tlog.Warn.Printf("doRead: truncating oversized read: %d to %d bytes", + length, fuse.MAX_KERNEL_WRITE) + }) + length = fuse.MAX_KERNEL_WRITE + } // Make sure we have the file ID. f.fileTableEntry.HeaderLock.RLock() if f.fileTableEntry.ID == nil { @@ -170,7 +182,8 @@ func (f *file) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Statu blocks := f.contentEnc.ExplodePlainRange(off, length) alignedOffset, alignedLength := blocks[0].JointCiphertextRange(blocks) skip := blocks[0].Skip - tlog.Debug.Printf("JointCiphertextRange(%d, %d) -> %d, %d, %d", off, length, alignedOffset, alignedLength, skip) + tlog.Debug.Printf("doRead: off=%d len=%d -> off=%d len=%d skip=%d\n", + off, length, alignedOffset, alignedLength, skip) ciphertext := f.fs.contentEnc.CReqPool.Get() ciphertext = ciphertext[:int(alignedLength)] -- cgit v1.2.3