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