From b23e21f61fc51ffa9c1c823778553925e1cc115e Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 2 Jun 2021 18:20:05 +0200 Subject: fusefrontend: catch ReadAt integer overflow Discovered by xfstests generic/564 . Failure was: generic/564 - output mismatch (see /opt/fuse-xfstests/results//generic/564.out.bad) --- tests/generic/564.out 2021-05-08 21:11:05.307395966 +0200 +++ /opt/fuse-xfstests/results//generic/564.out.bad 2021-05-19 19:01:16.912888879 +0200 @@ -31,7 +31,7 @@ source range beyond 8TiB returns 0 destination range beyond 8TiB returns EFBIG -copy_range: File too large +copy_range: Function not implemented --- internal/fusefrontend/file.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'internal') diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go index 33a3cbe..cbf78e9 100644 --- a/internal/fusefrontend/file.go +++ b/internal/fusefrontend/file.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "log" + "math" "os" "sync" "syscall" @@ -178,6 +179,10 @@ func (f *File) doRead(dst []byte, off uint64, length uint64) ([]byte, syscall.Er // Read the backing ciphertext in one go blocks := f.contentEnc.ExplodePlainRange(off, length) alignedOffset, alignedLength := blocks[0].JointCiphertextRange(blocks) + // f.fd.ReadAt takes an int64! + if alignedOffset > math.MaxInt64 { + return nil, syscall.EFBIG + } skip := blocks[0].Skip tlog.Debug.Printf("doRead: off=%d len=%d -> off=%d len=%d skip=%d\n", off, length, alignedOffset, alignedLength, skip) @@ -320,9 +325,13 @@ func (f *File) doWrite(data []byte, off int64) (uint32, syscall.Errno) { // Preallocate so we cannot run out of space in the middle of the write. // This prevents partially written (=corrupt) blocks. var err error - cOff := int64(blocks[0].BlockCipherOff()) + cOff := blocks[0].BlockCipherOff() + // f.fd.WriteAt & syscallcompat.EnospcPrealloc take int64 offsets! + if cOff > math.MaxInt64 { + return 0, syscall.EFBIG + } if !f.rootNode.args.NoPrealloc { - err = syscallcompat.EnospcPrealloc(f.intFd(), cOff, int64(len(ciphertext))) + err = syscallcompat.EnospcPrealloc(f.intFd(), int64(cOff), int64(len(ciphertext))) if err != nil { if !syscallcompat.IsENOSPC(err) { tlog.Warn.Printf("ino%d fh%d: doWrite: prealloc failed: %v", f.qIno.Ino, f.intFd(), err) @@ -339,7 +348,7 @@ func (f *File) doWrite(data []byte, off int64) (uint32, syscall.Errno) { } } // Write - _, err = f.fd.WriteAt(ciphertext, cOff) + _, err = f.fd.WriteAt(ciphertext, int64(cOff)) // Return memory to CReqPool f.rootNode.contentEnc.CReqPool.Put(ciphertext) if err != nil { -- cgit v1.2.3