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