From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40984) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X4Z6A-0004RA-Ff for qemu-devel@nongnu.org; Tue, 08 Jul 2014 13:23:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X4Z5f-0000HN-Ju for qemu-devel@nongnu.org; Tue, 08 Jul 2014 13:22:34 -0400 Received: from e33.co.us.ibm.com ([32.97.110.151]:60244) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X4Z5f-0000GM-DK for qemu-devel@nongnu.org; Tue, 08 Jul 2014 13:22:03 -0400 Received: from /spool/local by e33.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 8 Jul 2014 11:22:02 -0600 From: Michael Roth Date: Tue, 8 Jul 2014 12:17:53 -0500 Message-Id: <1404839947-1086-83-git-send-email-mdroth@linux.vnet.ibm.com> In-Reply-To: <1404839947-1086-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1404839947-1086-1-git-send-email-mdroth@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH 082/156] vpc/vhd: add bounds check for max_table_entries and block_size (CVE-2014-0144) List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: qemu-stable@nongnu.org From: Jeff Cody This adds checks to make sure that max_table_entries and block_size are in sane ranges. Memory is allocated based on max_table_entries, and block_size is used to calculate indices into that allocated memory, so if these values are incorrect that can lead to potential unbounded memory allocation, or invalid memory accesses. Also, the allocation of the pagetable is changed from g_malloc0() to qemu_blockalign(). Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi (cherry picked from commit 97f1c45c6f456572e5b504b8614e4a69e23b8e3a) Signed-off-by: Michael Roth --- block/vpc.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index 577cc45..4acf154 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -45,6 +45,8 @@ enum vhd_type { // Seconds since Jan 1, 2000 0:00:00 (UTC) #define VHD_TIMESTAMP_BASE 946684800 +#define VHD_MAX_SECTORS (65535LL * 255 * 255) + // always big-endian typedef struct vhd_footer { char creator[8]; // "conectix" @@ -164,6 +166,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, VHDDynDiskHeader *dyndisk_header; uint8_t buf[HEADER_SIZE]; uint32_t checksum; + uint64_t computed_size; int disk_type = VHD_DYNAMIC; int ret; @@ -221,7 +224,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, } /* Allow a maximum disk size of approximately 2 TB */ - if (bs->total_sectors >= 65535LL * 255 * 255) { + if (bs->total_sectors >= VHD_MAX_SECTORS) { ret = -EFBIG; goto fail; } @@ -244,7 +247,23 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511; s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries); - s->pagetable = g_malloc(s->max_table_entries * 4); + + if ((bs->total_sectors * 512) / s->block_size > 0xffffffffU) { + ret = -EINVAL; + goto fail; + } + if (s->max_table_entries > (VHD_MAX_SECTORS * 512) / s->block_size) { + ret = -EINVAL; + goto fail; + } + + computed_size = (uint64_t) s->max_table_entries * s->block_size; + if (computed_size < bs->total_sectors * 512) { + ret = -EINVAL; + goto fail; + } + + s->pagetable = qemu_blockalign(bs, s->max_table_entries * 4); s->bat_offset = be64_to_cpu(dyndisk_header->table_offset); @@ -297,7 +316,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, return 0; fail: - g_free(s->pagetable); + qemu_vfree(s->pagetable); #ifdef CACHE g_free(s->pageentry_u8); #endif @@ -819,7 +838,7 @@ static int vpc_has_zero_init(BlockDriverState *bs) static void vpc_close(BlockDriverState *bs) { BDRVVPCState *s = bs->opaque; - g_free(s->pagetable); + qemu_vfree(s->pagetable); #ifdef CACHE g_free(s->pageentry_u8); #endif -- 1.9.1