* [Qemu-devel] [PATCH v2 for-2.0 0/2] Bounds checking for VDI
@ 2014-03-28 15:42 Jeff Cody
2014-03-28 15:42 ` [Qemu-devel] [PATCH v2 for-2.0 1/2] vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144) Jeff Cody
2014-03-28 15:42 ` [Qemu-devel] [PATCH v2 for-2.0 2/2] block: vdi bounds check qemu-io tests Jeff Cody
0 siblings, 2 replies; 3+ messages in thread
From: Jeff Cody @ 2014-03-28 15:42 UTC (permalink / raw)
To: qemu-devel; +Cc: kwolf, sw, stefanha
This is v2 of the patches from Stefan Hajnoczi's pull request for CVE patches.
Changes from v1:
Patch 1: * Use DEFAULT_CLUSTER_SIZE instead of new
VDI_BLOCK_SIZE (thanks Stefan Weil)
* More informative error messages (thanks Stefan Weil)
* Return -ENOTSUP instead of -EINVAL on images
that exceed the maximum allowed size. These may
not be against spec, they are just currently unsupported.
* Fix wrong error message, introduced in commit
5b7aa9b56d1bfc79916262f380c3fc7961becb50 (thanks Stefan Weil)
Patch 2: * Update tests results to take in account new error messages.
Jeff Cody (2):
vdi: add bounds checks for blocks_in_image and disk_size header fields
(CVE-2014-0144)
block: vdi bounds check qemu-io tests
block/vdi.c | 37 ++++++++++++++--
tests/qemu-iotests/084 | 104 +++++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/084.out | 33 ++++++++++++++
tests/qemu-iotests/group | 1 +
4 files changed, 171 insertions(+), 4 deletions(-)
create mode 100755 tests/qemu-iotests/084
create mode 100644 tests/qemu-iotests/084.out
--
1.8.3.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Qemu-devel] [PATCH v2 for-2.0 1/2] vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144)
2014-03-28 15:42 [Qemu-devel] [PATCH v2 for-2.0 0/2] Bounds checking for VDI Jeff Cody
@ 2014-03-28 15:42 ` Jeff Cody
2014-03-28 15:42 ` [Qemu-devel] [PATCH v2 for-2.0 2/2] block: vdi bounds check qemu-io tests Jeff Cody
1 sibling, 0 replies; 3+ messages in thread
From: Jeff Cody @ 2014-03-28 15:42 UTC (permalink / raw)
To: qemu-devel; +Cc: kwolf, sw, stefanha
The maximum blocks_in_image is 0xffffffff / 4, which also limits the
maximum disk_size for a VDI image to 1024TB. Note that this is the maximum
size that QEMU will currently support with this driver, not necessarily the
maximum size allowed by the image format.
This also fixes an incorrect error message, a bug introduced by commit
5b7aa9b56d1bfc79916262f380c3fc7961becb50 (Reported by Stefan Weil)
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/vdi.c | 37 +++++++++++++++++++++++++++++++++----
1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/block/vdi.c b/block/vdi.c
index ac9a025..820cd37 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -120,6 +120,11 @@ typedef unsigned char uuid_t[16];
#define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
+/* max blocks in image is (0xffffffff / 4) */
+#define VDI_BLOCKS_IN_IMAGE_MAX 0x3fffffff
+#define VDI_DISK_SIZE_MAX ((uint64_t)VDI_BLOCKS_IN_IMAGE_MAX * \
+ (uint64_t)DEFAULT_CLUSTER_SIZE)
+
#if !defined(CONFIG_UUID)
static inline void uuid_generate(uuid_t out)
{
@@ -385,6 +390,14 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
vdi_header_print(&header);
#endif
+ if (header.disk_size > VDI_DISK_SIZE_MAX) {
+ error_setg(errp, "Unsupported VDI image size (size is 0x%" PRIx64
+ ", max supported is 0x%" PRIx64 ")",
+ header.disk_size, VDI_DISK_SIZE_MAX);
+ ret = -ENOTSUP;
+ goto fail;
+ }
+
if (header.disk_size % SECTOR_SIZE != 0) {
/* 'VBoxManage convertfromraw' can create images with odd disk sizes.
We accept them but round the disk size to the next multiple of
@@ -420,9 +433,9 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
header.sector_size, SECTOR_SIZE);
ret = -ENOTSUP;
goto fail;
- } else if (header.block_size != 1 * MiB) {
- error_setg(errp, "unsupported VDI image (sector size %u is not %u)",
- header.block_size, 1 * MiB);
+ } else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
+ error_setg(errp, "unsupported VDI image (block size %u is not %u)",
+ header.block_size, DEFAULT_CLUSTER_SIZE);
ret = -ENOTSUP;
goto fail;
} else if (header.disk_size >
@@ -441,6 +454,12 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
error_setg(errp, "unsupported VDI image (non-NULL parent UUID)");
ret = -ENOTSUP;
goto fail;
+ } else if (header.blocks_in_image > VDI_BLOCKS_IN_IMAGE_MAX) {
+ error_setg(errp, "unsupported VDI image "
+ "(too many blocks %u, max is %u)",
+ header.blocks_in_image, VDI_BLOCKS_IN_IMAGE_MAX);
+ ret = -ENOTSUP;
+ goto fail;
}
bs->total_sectors = header.disk_size / SECTOR_SIZE;
@@ -689,11 +708,20 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
options++;
}
+ if (bytes > VDI_DISK_SIZE_MAX) {
+ result = -ENOTSUP;
+ error_setg(errp, "Unsupported VDI image size (size is 0x%" PRIx64
+ ", max supported is 0x%" PRIx64 ")",
+ bytes, VDI_DISK_SIZE_MAX);
+ goto exit;
+ }
+
fd = qemu_open(filename,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
if (fd < 0) {
- return -errno;
+ result = -errno;
+ goto exit;
}
/* We need enough blocks to store the given disk size,
@@ -754,6 +782,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
result = -errno;
}
+exit:
return result;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [Qemu-devel] [PATCH v2 for-2.0 2/2] block: vdi bounds check qemu-io tests
2014-03-28 15:42 [Qemu-devel] [PATCH v2 for-2.0 0/2] Bounds checking for VDI Jeff Cody
2014-03-28 15:42 ` [Qemu-devel] [PATCH v2 for-2.0 1/2] vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144) Jeff Cody
@ 2014-03-28 15:42 ` Jeff Cody
1 sibling, 0 replies; 3+ messages in thread
From: Jeff Cody @ 2014-03-28 15:42 UTC (permalink / raw)
To: qemu-devel; +Cc: kwolf, sw, stefanha
This test checks for proper bounds checking of some VDI input
headers. The following is checked:
1. Max image size (1024TB) with the appropriate Blocks In Image
value (0x3fffffff) is detected as valid.
2. Image size exceeding max (1024TB) is seen as invalid
3. Valid image size but with Blocks In Image value that is too
small fails
4. Blocks In Image size exceeding max (0x3fffffff) is seen as invalid
5. 64MB image, with 64 Blocks In Image, and 1MB Block Size is seen
as valid
6. Block Size < 1MB not supported
7. Block Size > 1MB not supported
Signed-off-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
tests/qemu-iotests/084 | 104 +++++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/084.out | 33 ++++++++++++++
tests/qemu-iotests/group | 1 +
3 files changed, 138 insertions(+)
create mode 100755 tests/qemu-iotests/084
create mode 100644 tests/qemu-iotests/084.out
diff --git a/tests/qemu-iotests/084 b/tests/qemu-iotests/084
new file mode 100755
index 0000000..10a5a65
--- /dev/null
+++ b/tests/qemu-iotests/084
@@ -0,0 +1,104 @@
+#!/bin/bash
+#
+# Test case for VDI header corruption; image too large, and too many blocks
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=jcody@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# This tests vdi-specific header fields
+_supported_fmt vdi
+_supported_proto generic
+_supported_os Linux
+
+ds_offset=368 # disk image size field offset
+bs_offset=376 # block size field offset
+bii_offset=384 # block in image field offset
+
+echo
+echo "=== Testing image size bounds ==="
+echo
+_make_test_img 64M
+
+# check for image size too large
+# poke max image size, and appropriate blocks_in_image value
+echo "Test 1: Maximum size (1024 TB):"
+poke_file "$TEST_IMG" "$ds_offset" "\x00\x00\xf0\xff\xff\xff\x03\x00"
+poke_file "$TEST_IMG" "$bii_offset" "\xff\xff\xff\x3f"
+_img_info
+
+echo
+echo "Test 2: Size too large (1024TB + 1)"
+# This should be too large (-EINVAL):
+poke_file "$TEST_IMG" "$ds_offset" "\x00\x00\xf1\xff\xff\xff\x03\x00"
+_img_info
+
+echo
+echo "Test 3: Size valid (64M), but Blocks In Image too small (63)"
+# This sets the size to 64M, but with a blocks_in_image size that is
+# too small
+poke_file "$TEST_IMG" "$ds_offset" "\x00\x00\x00\x04\x00\x00\x00\x00"
+# For a 64M image, we would need a blocks_in_image value of at least 64,
+# so 63 should be too small and give us -ENOTSUP
+poke_file "$TEST_IMG" "$bii_offset" "\x3f\x00\x00\x00"
+_img_info
+
+echo
+echo "Test 4: Size valid (64M), but Blocks In Image exceeds max allowed"
+# Now check the bounds of blocks_in_image - 0x3fffffff should be the max
+# value here, and we should get -ENOTSUP
+poke_file "$TEST_IMG" "$bii_offset" "\x00\x00\x00\x40"
+_img_info
+
+# Finally, 1MB is the only block size supported. Verify that
+# a value != 1MB results in error, both smaller and larger
+echo
+echo "Test 5: Valid Image: 64MB, Blocks In Image 64, Block Size 1MB"
+poke_file "$TEST_IMG" "$bii_offset" "\x40\x00\x00\x00" # reset bii to valid
+poke_file "$TEST_IMG" "$bs_offset" "\x00\x00\x10\x00" # valid
+_img_info
+echo
+echo "Test 6: Block Size != 1MB; too small test (1MB - 1)"
+poke_file "$TEST_IMG" "$bs_offset" "\xff\xff\x0f\x00" # invalid (too small)
+_img_info
+echo
+echo "Test 7: Block Size != 1MB; too large test (1MB + 1)"
+poke_file "$TEST_IMG" "$bs_offset" "\x00\x00\x11\x00" # invalid (too large)
+_img_info
+# success, all done
+echo
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/084.out b/tests/qemu-iotests/084.out
new file mode 100644
index 0000000..842646e
--- /dev/null
+++ b/tests/qemu-iotests/084.out
@@ -0,0 +1,33 @@
+QA output created by 084
+
+=== Testing image size bounds ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Test 1: Maximum size (1024 TB):
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 1024T (1125899905794048 bytes)
+cluster_size: 1048576
+
+Test 2: Size too large (1024TB + 1)
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported VDI image size (size is 0x3fffffff10000, max supported is 0x3fffffff00000)
+
+Test 3: Size valid (64M), but Blocks In Image too small (63)
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (disk size 67108864, image bitmap has room for 66060288)
+
+Test 4: Size valid (64M), but Blocks In Image exceeds max allowed
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (too many blocks 1073741824, max is 1073741823)
+
+Test 5: Valid Image: 64MB, Blocks In Image 64, Block Size 1MB
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 64M (67108864 bytes)
+cluster_size: 1048576
+
+Test 6: Block Size != 1MB; too small test (1MB - 1)
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (block size 1048575 is not 1048576)
+
+Test 7: Block Size != 1MB; too large test (1MB + 1)
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (block size 1114112 is not 1048576)
+
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index ee09ebc..51fa5b6 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -86,6 +86,7 @@
081 rw auto
082 rw auto quick
083 rw auto
+084 img auto
085 rw auto
086 rw auto quick
087 rw auto
--
1.8.3.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-03-28 15:42 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-28 15:42 [Qemu-devel] [PATCH v2 for-2.0 0/2] Bounds checking for VDI Jeff Cody
2014-03-28 15:42 ` [Qemu-devel] [PATCH v2 for-2.0 1/2] vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144) Jeff Cody
2014-03-28 15:42 ` [Qemu-devel] [PATCH v2 for-2.0 2/2] block: vdi bounds check qemu-io tests Jeff Cody
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).