diff options
author | Dylan Reid <dgreid@chromium.org> | 2019-06-14 11:41:07 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-06-21 19:22:33 +0000 |
commit | 70d7bad28414e4b0d8bdf2d5eb85618a3b1e83c6 (patch) | |
tree | 529536de447e8b5b09fe308b49eb273215e39726 | |
parent | c9f254b1921335231b32550b5ae6b8416e1ca7aa (diff) | |
download | crosvm-70d7bad28414e4b0d8bdf2d5eb85618a3b1e83c6.tar crosvm-70d7bad28414e4b0d8bdf2d5eb85618a3b1e83c6.tar.gz crosvm-70d7bad28414e4b0d8bdf2d5eb85618a3b1e83c6.tar.bz2 crosvm-70d7bad28414e4b0d8bdf2d5eb85618a3b1e83c6.tar.lz crosvm-70d7bad28414e4b0d8bdf2d5eb85618a3b1e83c6.tar.xz crosvm-70d7bad28414e4b0d8bdf2d5eb85618a3b1e83c6.tar.zst crosvm-70d7bad28414e4b0d8bdf2d5eb85618a3b1e83c6.zip |
qcow: disallow crazy l1 table sizes
Before this change, a corrupt or malicious qcow file could cause crosvm to allocate absurd amounts of memory. The fuzzer found this case, limit the L1 table size so it can't cause issues. BUG=chromium:974123 TEST=run fuzzer locally, add unit test Change-Id: Ieb6db6c87f71df726b3cc9a98404581fe32fb1ce Signed-off-by: Dylan Reid <dgreid@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1660890 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com>
-rw-r--r-- | qcow/src/qcow.rs | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/qcow/src/qcow.rs b/qcow/src/qcow.rs index 4b781f4..7528773 100644 --- a/qcow/src/qcow.rs +++ b/qcow/src/qcow.rs @@ -38,6 +38,7 @@ pub enum Error { InvalidClusterSize, InvalidIndex, InvalidL1TableOffset, + InvalidL1TableSize(u32), InvalidMagic, InvalidOffset(u64), InvalidRefcountTableOffset, @@ -83,6 +84,7 @@ impl Display for Error { InvalidClusterSize => write!(f, "invalid cluster size"), InvalidIndex => write!(f, "invalid index"), InvalidL1TableOffset => write!(f, "invalid L1 table offset"), + InvalidL1TableSize(size) => write!(f, "invalid L1 table size {}", size), InvalidMagic => write!(f, "invalid magic"), InvalidOffset(_) => write!(f, "invalid offset"), InvalidRefcountTableOffset => write!(f, "invalid refcount table offset"), @@ -357,6 +359,11 @@ impl QcowFile { return Err(Error::UnsupportedVersion(header.version)); } + // Make sure that the L1 table fits in RAM. + if u64::from(header.l1_size) > MAX_RAM_POINTER_TABLE_SIZE { + return Err(Error::InvalidL1TableSize(header.l1_size)); + } + let cluster_bits: u32 = header.cluster_bits; if cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS { return Err(Error::InvalidClusterSize); @@ -1809,6 +1816,15 @@ mod tests { } #[test] + fn test_huge_l1_table() { + let mut header = valid_header(); + header[36] = 0x12; + with_basic_file(&header, |disk_file: File| { + QcowFile::from(disk_file).expect_err("Failed to create file."); + }); + } + + #[test] fn test_header_1_tb_file_min_cluster() { let mut header = test_huge_header(); header[24] = 0; |