9ae3a8
From e00b646f642f10be545014c866a71b268d90e67a Mon Sep 17 00:00:00 2001
9ae3a8
From: Fam Zheng <famz@redhat.com>
9ae3a8
Date: Tue, 6 Aug 2013 15:44:53 +0800
9ae3a8
Subject: [PATCH 07/13] vmdk: check l1 size before opening image
9ae3a8
9ae3a8
Message-id: <1377573001-27070-8-git-send-email-famz@redhat.com>
9ae3a8
Patchwork-id: 53786
9ae3a8
O-Subject: [RHEL-7 qemu-kvm PATCH 07/13] vmdk: check l1 size before opening image
9ae3a8
Bugzilla: 995866
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
9ae3a8
L1 table size is calculated from capacity, granularity and l2 table
9ae3a8
size. If capacity is too big or later two are too small, the L1 table
9ae3a8
will be too big to allocate in memory. Limit it to a reasonable range.
9ae3a8
9ae3a8
Signed-off-by: Fam Zheng <famz@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit 2c43e43c8cec130fff95ef720a860e91efb36685)
9ae3a8
Signed-off-by: Fam Zheng <famz@redhat.com>
9ae3a8
---
9ae3a8
 block/vmdk.c               |    8 ++++++++
9ae3a8
 tests/qemu-iotests/059     |    8 ++++++++
9ae3a8
 tests/qemu-iotests/059.out |    6 ++++++
9ae3a8
 3 files changed, 22 insertions(+), 0 deletions(-)
9ae3a8
9ae3a8
diff --git a/block/vmdk.c b/block/vmdk.c
9ae3a8
index b2a3fe2..58163ef 100644
9ae3a8
--- a/block/vmdk.c
9ae3a8
+++ b/block/vmdk.c
9ae3a8
@@ -597,6 +597,14 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
9ae3a8
     }
9ae3a8
     l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
9ae3a8
                 / l1_entry_sectors;
9ae3a8
+    if (l1_size > 512 * 1024 * 1024) {
9ae3a8
+        /* although with big capacity and small l1_entry_sectors, we can get a
9ae3a8
+         * big l1_size, we don't want unbounded value to allocate the table.
9ae3a8
+         * Limit it to 512M, which is 16PB for default cluster and L2 table
9ae3a8
+         * size */
9ae3a8
+        error_report("L1 size too big");
9ae3a8
+        return -EFBIG;
9ae3a8
+    }
9ae3a8
     if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) {
9ae3a8
         l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9;
9ae3a8
     }
9ae3a8
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
9ae3a8
index 301eaca..b03429d 100755
9ae3a8
--- a/tests/qemu-iotests/059
9ae3a8
+++ b/tests/qemu-iotests/059
9ae3a8
@@ -43,6 +43,7 @@ _supported_fmt vmdk
9ae3a8
 _supported_proto generic
9ae3a8
 _supported_os Linux
9ae3a8
 
9ae3a8
+capacity_offset=16
9ae3a8
 granularity_offset=20
9ae3a8
 grain_table_size_offset=44
9ae3a8
 
9ae3a8
@@ -58,6 +59,13 @@ _make_test_img 64M
9ae3a8
 poke_file "$TEST_IMG" "$grain_table_size_offset" "\xff\xff\xff\xff"
9ae3a8
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
9ae3a8
 
9ae3a8
+echo "=== Testing too big L1 table size ==="
9ae3a8
+echo
9ae3a8
+_make_test_img 64M
9ae3a8
+poke_file "$TEST_IMG" "$capacity_offset" "\xff\xff\xff\xff"
9ae3a8
+poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
9ae3a8
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
9ae3a8
+
9ae3a8
 # success, all done
9ae3a8
 echo "*** done"
9ae3a8
 rm -f $seq.full
9ae3a8
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
9ae3a8
index 583955f..9e715e5 100644
9ae3a8
--- a/tests/qemu-iotests/059.out
9ae3a8
+++ b/tests/qemu-iotests/059.out
9ae3a8
@@ -11,4 +11,10 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
9ae3a8
 L2 table size too big
9ae3a8
 qemu-io: can't open device TEST_DIR/t.vmdk
9ae3a8
 no file open, try 'help open'
9ae3a8
+=== Testing too big L1 table size ===
9ae3a8
+
9ae3a8
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
9ae3a8
+L1 size too big
9ae3a8
+qemu-io: can't open device TEST_DIR/t.vmdk
9ae3a8
+no file open, try 'help open'
9ae3a8
 *** done
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8