f3a92caa76
CVE-2014-0150: virtio-net: buffer overflow in virtio_net_handle_mac() function (bz #1086775, bz #1078846) CVE-2013-4544: vmxnet3: bounds checking buffer overrun (bz #1087513, bz #1087522) CVE-2014-2894: out of bounds buffer accesses, guest triggerable via IDE SMART (bz #1087981, bz #1087971)
112 lines
4.1 KiB
Diff
112 lines
4.1 KiB
Diff
From ae25d949d7d500e2b59cd442e914c828823a5f2c Mon Sep 17 00:00:00 2001
|
|
From: Jeff Cody <jcody@redhat.com>
|
|
Date: Fri, 28 Mar 2014 11:42:24 -0400
|
|
Subject: [PATCH] vdi: add bounds checks for blocks_in_image and disk_size
|
|
header fields (CVE-2014-0144)
|
|
|
|
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>
|
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
(cherry picked from commit 63fa06dc978f3669dbfd9443b33cde9e2a7f4b41)
|
|
|
|
Conflicts:
|
|
block/vdi.c
|
|
---
|
|
block/vdi.c | 35 +++++++++++++++++++++++++++++++++--
|
|
1 file changed, 33 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/block/vdi.c b/block/vdi.c
|
|
index 8a91525..63d509e 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)
|
|
{
|
|
@@ -383,6 +388,14 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags)
|
|
vdi_header_print(&header);
|
|
#endif
|
|
|
|
+ if (header.disk_size > VDI_DISK_SIZE_MAX) {
|
|
+ fprintf(stderr, "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
|
|
@@ -415,8 +428,10 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags)
|
|
logout("unsupported sector size %u B\n", header.sector_size);
|
|
ret = -ENOTSUP;
|
|
goto fail;
|
|
- } else if (header.block_size != 1 * MiB) {
|
|
logout("unsupported block size %u B\n", header.block_size);
|
|
+ } else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
|
|
+ logout("unsupported VDI image (block size %u is not %u)",
|
|
+ header.block_size, DEFAULT_CLUSTER_SIZE);
|
|
ret = -ENOTSUP;
|
|
goto fail;
|
|
} else if (header.disk_size >
|
|
@@ -432,6 +447,12 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags)
|
|
logout("parent uuid != 0, unsupported\n");
|
|
ret = -ENOTSUP;
|
|
goto fail;
|
|
+ } else if (header.blocks_in_image > VDI_BLOCKS_IN_IMAGE_MAX) {
|
|
+ fprintf(stderr, "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;
|
|
@@ -668,11 +689,20 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
|
|
options++;
|
|
}
|
|
|
|
+ if (bytes > VDI_DISK_SIZE_MAX) {
|
|
+ result = -ENOTSUP;
|
|
+ fprintf(stderr, "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,
|
|
@@ -733,6 +763,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
|
|
result = -errno;
|
|
}
|
|
|
|
+exit:
|
|
return result;
|
|
}
|
|
|