Skip to content

Commit

Permalink
fusefrontend: clamp oversized reads
Browse files Browse the repository at this point in the history
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
#145
  • Loading branch information
rfjakob committed Oct 17, 2017
1 parent 64e5906 commit 3009ec9
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
2 changes: 2 additions & 0 deletions internal/contentenc/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ func (be *ContentEnc) DecryptBlock(ciphertext []byte, blockNo uint64, fileID []b
const encryptMaxSplit = 2

// EncryptBlocks is like EncryptBlock but takes multiple plaintext blocks.
// Returns a byte slice from CReqPool - so don't forget to return it
// to the pool.
func (be *ContentEnc) EncryptBlocks(plaintextBlocks [][]byte, firstBlockNo uint64, fileID []byte) []byte {
ciphertextBlocks := make([][]byte, len(plaintextBlocks))
// For large writes, we parallelize encryption.
Expand Down
15 changes: 14 additions & 1 deletion internal/fusefrontend/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 {
Expand Down Expand Up @@ -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)]
Expand Down

0 comments on commit 3009ec9

Please sign in to comment.