|
|
9ae3a8 |
From 6ce116dda5d5a7708d660e32713ff40fc3f749ef Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Jeff Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
Date: Tue, 25 Mar 2014 14:23:24 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 17/49] vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
Message-id: <1395753835-7591-18-git-send-email-kwolf@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: n/a
|
|
|
9ae3a8 |
O-Subject: [virt-devel] [EMBARGOED RHEL-7.0 qemu-kvm PATCH 17/48] vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144)
|
|
|
9ae3a8 |
Bugzilla: 1079455
|
|
|
9ae3a8 |
RH-Acked-by: Jeff Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
From: Jeff Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1079455
|
|
|
9ae3a8 |
Upstream status: Embargoed
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
The maximum blocks_in_image is 0xffffffff / 4, which also limits the
|
|
|
9ae3a8 |
maximum disk_size for a VDI image.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Jeff Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Conflicts:
|
|
|
9ae3a8 |
block/vdi.c
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
block/vdi.c | 26 ++++++++++++++++++++++++--
|
|
|
9ae3a8 |
1 files changed, 24 insertions(+), 2 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/block/vdi.c b/block/vdi.c
|
|
|
9ae3a8 |
index f973883..0457298 100644
|
|
|
9ae3a8 |
--- a/block/vdi.c
|
|
|
9ae3a8 |
+++ b/block/vdi.c
|
|
|
9ae3a8 |
@@ -120,6 +120,12 @@ typedef unsigned char uuid_t[16];
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
#define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+#define VDI_BLOCK_SIZE (1 * MiB)
|
|
|
9ae3a8 |
+/* max blocks in image is (0xffffffff / 4) */
|
|
|
9ae3a8 |
+#define VDI_BLOCKS_IN_IMAGE_MAX 0x3fffffff
|
|
|
9ae3a8 |
+#define VDI_DISK_SIZE_MAX ((uint64_t)VDI_BLOCKS_IN_IMAGE_MAX * \
|
|
|
9ae3a8 |
+ (uint64_t)VDI_BLOCK_SIZE)
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
#if !defined(CONFIG_UUID)
|
|
|
9ae3a8 |
static inline void uuid_generate(uuid_t out)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
@@ -385,6 +391,11 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
|
|
9ae3a8 |
vdi_header_print(&header);
|
|
|
9ae3a8 |
#endif
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+ if (header.disk_size > VDI_DISK_SIZE_MAX) {
|
|
|
9ae3a8 |
+ ret = -EINVAL;
|
|
|
9ae3a8 |
+ goto fail;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
if (header.disk_size % SECTOR_SIZE != 0) {
|
|
|
9ae3a8 |
/* 'VBoxManage convertfromraw' can create images with odd disk sizes.
|
|
|
9ae3a8 |
We accept them but round the disk size to the next multiple of
|
|
|
9ae3a8 |
@@ -417,7 +428,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
|
|
9ae3a8 |
logout("unsupported sector size %u B\n", header.sector_size);
|
|
|
9ae3a8 |
ret = -ENOTSUP;
|
|
|
9ae3a8 |
goto fail;
|
|
|
9ae3a8 |
- } else if (header.block_size != 1 * MiB) {
|
|
|
9ae3a8 |
+ } else if (header.block_size != VDI_BLOCK_SIZE) {
|
|
|
9ae3a8 |
logout("unsupported block size %u B\n", header.block_size);
|
|
|
9ae3a8 |
ret = -ENOTSUP;
|
|
|
9ae3a8 |
goto fail;
|
|
|
9ae3a8 |
@@ -434,6 +445,10 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
|
|
9ae3a8 |
logout("parent uuid != 0, unsupported\n");
|
|
|
9ae3a8 |
ret = -ENOTSUP;
|
|
|
9ae3a8 |
goto fail;
|
|
|
9ae3a8 |
+ } else if (header.blocks_in_image > VDI_BLOCKS_IN_IMAGE_MAX) {
|
|
|
9ae3a8 |
+ logout("unsupported number of blocks in image\n");
|
|
|
9ae3a8 |
+ ret = -ENOTSUP;
|
|
|
9ae3a8 |
+ goto fail;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
bs->total_sectors = header.disk_size / SECTOR_SIZE;
|
|
|
9ae3a8 |
@@ -682,11 +697,17 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
|
|
9ae3a8 |
options++;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+ if (bytes > VDI_DISK_SIZE_MAX) {
|
|
|
9ae3a8 |
+ result = -EINVAL;
|
|
|
9ae3a8 |
+ goto exit;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
fd = qemu_open(filename,
|
|
|
9ae3a8 |
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
|
|
|
9ae3a8 |
0644);
|
|
|
9ae3a8 |
if (fd < 0) {
|
|
|
9ae3a8 |
- return -errno;
|
|
|
9ae3a8 |
+ result = -errno;
|
|
|
9ae3a8 |
+ goto exit;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
/* We need enough blocks to store the given disk size,
|
|
|
9ae3a8 |
@@ -747,6 +768,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
|
|
9ae3a8 |
result = -errno;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+exit:
|
|
|
9ae3a8 |
return result;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.1
|
|
|
9ae3a8 |
|