diff options
author | Jakob Unterwurzacher | 2021-06-02 18:20:05 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2021-06-02 18:20:05 +0200 |
commit | b23e21f61fc51ffa9c1c823778553925e1cc115e (patch) | |
tree | 14febe8934716ae8589b2495636a5dceec935180 /internal | |
parent | 04858ddd222bbf7156f33f99cfb293a9b1e15ec8 (diff) |
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
Diffstat (limited to 'internal')
-rw-r--r-- | internal/fusefrontend/file.go | 15 |
1 files changed, 12 insertions, 3 deletions
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 { |