From patchwork Tue Apr 1 17:18:57 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 336070 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id B9EF11400B2 for ; Wed, 2 Apr 2014 04:28:26 +1100 (EST) Received: from localhost ([::1]:33485 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WV2U4-00046h-BV for incoming@patchwork.ozlabs.org; Tue, 01 Apr 2014 13:28:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42014) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WV2Mj-00016P-Rt for qemu-devel@nongnu.org; Tue, 01 Apr 2014 13:20:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WV2Md-0003Dj-Ex for qemu-devel@nongnu.org; Tue, 01 Apr 2014 13:20:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:61247) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WV2Md-0003Dd-6K for qemu-devel@nongnu.org; Tue, 01 Apr 2014 13:20:43 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s31HKeit020926 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 1 Apr 2014 13:20:41 -0400 Received: from localhost (ovpn-112-69.ams2.redhat.com [10.36.112.69]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s31HKdv9017281; Tue, 1 Apr 2014 13:20:40 -0400 From: Stefan Hajnoczi To: Date: Tue, 1 Apr 2014 19:18:57 +0200 Message-Id: <1396372769-11688-20-git-send-email-stefanha@redhat.com> In-Reply-To: <1396372769-11688-1-git-send-email-stefanha@redhat.com> References: <1396372769-11688-1-git-send-email-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Kevin Wolf , Peter Maydell , Jeff Cody , Stefan Hajnoczi Subject: [Qemu-devel] [PULL for-2.0 19/51] vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Jeff Cody 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 Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi --- 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; }