summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan Reid <dgreid@chromium.org>2019-06-28 15:19:57 +1000
committerCommit Bot <commit-bot@chromium.org>2019-07-09 17:46:22 +0000
commit93b0c02227f3acf2c6ff127976875cf3ce98c003 (patch)
treed985c8753788fb6f9d486b3b605b58f835d1e41d
parenteecbccc4d9d70b2fd63681a2b3ced6a6aafe81bb (diff)
downloadcrosvm-93b0c02227f3acf2c6ff127976875cf3ce98c003.tar
crosvm-93b0c02227f3acf2c6ff127976875cf3ce98c003.tar.gz
crosvm-93b0c02227f3acf2c6ff127976875cf3ce98c003.tar.bz2
crosvm-93b0c02227f3acf2c6ff127976875cf3ce98c003.tar.lz
crosvm-93b0c02227f3acf2c6ff127976875cf3ce98c003.tar.xz
crosvm-93b0c02227f3acf2c6ff127976875cf3ce98c003.tar.zst
crosvm-93b0c02227f3acf2c6ff127976875cf3ce98c003.zip
qcow: limit the size of a qcow file
There are many corner cases when handling sizes that approach u64::max.
Limit the files to 16TB.

BUG=979458
TEST=Added unittest to check large disks fail

Signed-off-by: Dylan Reid <dgreid@chromium.org>
Change-Id: I93a87c17267ae69102f8d46ced9dbea8c686d093
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1679892
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
-rw-r--r--qcow/src/qcow.rs23
1 files changed, 22 insertions, 1 deletions
diff --git a/qcow/src/qcow.rs b/qcow/src/qcow.rs
index ceaf130..fba511d 100644
--- a/qcow/src/qcow.rs
+++ b/qcow/src/qcow.rs
@@ -77,7 +77,11 @@ impl Display for Error {
             BackingFilesNotSupported => write!(f, "backing files not supported"),
             CompressedBlocksNotSupported => write!(f, "compressed blocks not supported"),
             EvictingCache(e) => write!(f, "failed to evict cache: {}", e),
-            FileTooBig(size) => write!(f, "file larger than max of 1TB: {}", size),
+            FileTooBig(size) => write!(
+                f,
+                "file larger than max of {}: {}",
+                MAX_QCOW_FILE_SIZE, size
+            ),
             GettingFileSize(e) => write!(f, "failed to get file size: {}", e),
             GettingRefcount(e) => write!(f, "failed to get refcount: {}", e),
             InvalidClusterIndex => write!(f, "invalid cluster index"),
@@ -118,6 +122,9 @@ pub enum ImageType {
     Qcow2,
 }
 
+// Maximum data size supported.
+const MAX_QCOW_FILE_SIZE: u64 = 0x01 << 44; // 16 TB.
+
 // QCOW magic constant that starts the header.
 const QCOW_MAGIC: u32 = 0x5146_49fb;
 // Default to a cluster size of 2^DEFAULT_CLUSTER_BITS
@@ -370,6 +377,11 @@ impl QcowFile {
         }
         let cluster_size = 0x01u64 << cluster_bits;
 
+        // Limit the total size of the disk.
+        if header.size > MAX_QCOW_FILE_SIZE {
+            return Err(Error::FileTooBig(header.size));
+        }
+
         // No current support for backing files.
         if header.backing_file_offset != 0 {
             return Err(Error::BackingFilesNotSupported);
@@ -1816,6 +1828,15 @@ mod tests {
     }
 
     #[test]
+    fn test_header_crazy_file_size_rejected() {
+        let mut header = valid_header();
+        &mut header[24..32].copy_from_slice(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1e]);
+        with_basic_file(&header, |disk_file: File| {
+            QcowFile::from(disk_file).expect_err("Failed to create file.");
+        });
+    }
+
+    #[test]
     fn test_huge_l1_table() {
         let mut header = valid_header();
         header[36] = 0x12;