From: Stefan Weil <sw@weilnetz.de>
To: Jeff Cody <jcody@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>,
pmatouse@redhat.com, qemu-devel@nongnu.org,
Stefan Hajnoczi <stefanha@redhat.com>,
qemu-stable@nongnu.org
Subject: Re: [Qemu-devel] [PATCH for-2.0 16/47] vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144)
Date: Thu, 27 Mar 2014 20:58:38 +0100 [thread overview]
Message-ID: <533482EE.2060609@weilnetz.de> (raw)
In-Reply-To: <20140327185242.GE21833@localhost.localdomain>
Am 27.03.2014 19:52, schrieb Jeff Cody:
[...]
> I looked around, and I could not find a definitive source for a VDI
> specification. Do you know if there is a specified max size for a VDI
> image?
I used the reference which I also mentioned in the header comment of
block/vdi.c: http://forums.virtualbox.org/viewtopic.php?t=8046. It does
not say anything about a specific maximum size.
The image size is limited by some entries in VdiHeader: disk_size is 64
bit, so UINT64_MAX is a hard limit. blocks_in_image is 32 bit, so there
is another hard limit of UINT32_MAX * block_size where the default block
size is 1 MiB.
As you write below, the current implementation in block/vdi.c imposes
additional limits which are lower than the hard limits above: the block
cache is allocated and filled by functions which take a size_t argument.
>
> If we assume support for 64 bit size_t values, that may or may not be
> within the VDI spec (I don't know). But I think there are practical
> limits we need to set in place with our current driver implementation,
> as we currently dynamically allocate the block cache based on
> blocks_in_image * 4 * SECTOR_SIZE.
>
> Of course, this needs to be tempered with the notion of not breaking
> existing support for VDI images that are in-spec.
>
>>> +#define VDI_DISK_SIZE_MAX ((uint64_t)VDI_BLOCKS_IN_IMAGE_MAX * \
>>> + (uint64_t)VDI_BLOCK_SIZE)
>>> +
>>
>> This macro cannot be used because the block size might have a non
>> default value.
>>
>
> The VDI driver does not currently support non-default block sizes.
> There is partial support for vdi image creation for variable block
> sizes, but it is commented out (with a note saying it is untested).
> But for image open, the vdi_open() function currently has a hard check
> for header.block_size != 1MB.
I fixed this in the patch which I have sent this week. See
http://patchwork.ozlabs.org/patch/334116/.
>
> So, the above macro is in line with what the VDI driver supports, I
> believe.
>
> This was meant to be a bug-fix only, so adding in new support for
> non-default block sizes wasn't the original intent.
>
Agreed, but it's also good to make the necessary changes so that they go
into the right direction.
>
>>> #if !defined(CONFIG_UUID)
>>> static inline void uuid_generate(uuid_t out)
>>> {
>>> @@ -385,6 +391,11 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
>>> vdi_header_print(&header);
>>> #endif
>>>
>>> + if (header.disk_size > VDI_DISK_SIZE_MAX) {
>>
>> Here error_setg is missing. The style does not match the other checks.
>> More changes are needed because VDI_DISK_SIZE_MAX cannot be used.
>>
>
> I agree error_setg could be useful here.
>
>>> + ret = -EINVAL;
>>> + 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 +431,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) {
>>> + } else if (header.block_size != VDI_BLOCK_SIZE) {
>>> error_setg(errp, "unsupported VDI image (sector size %u is not %u)",
>>
>> Here is a copy+paste bug which was recently introduced.
>>
>
> Yes, the error message should be modified: s/sector/block
>
>
>>> - header.block_size, 1 * MiB);
>>> + header.block_size, VDI_BLOCK_SIZE);
>>
>> Replace VDI_BLOCK_SIZE by the existing macro here.
>>
>
> OK
>
>>> ret = -ENOTSUP;
>>> goto fail;
>>> } else if (header.disk_size >
>>> @@ -441,6 +452,10 @@ 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)");
>>
>> Fix test and improve error message (show limit) here.
>>
>>> + ret = -ENOTSUP;
>>> + goto fail;
>>> } > > > > bs->total_sectors = header.disk_size / SECTOR_SIZE;
>>> @@ -689,11 +704,17 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
>>> options++;
>>> }
>>>
>>> + if (bytes > VDI_DISK_SIZE_MAX) {
>>
>> Dto.
>>
>>> + result = -EINVAL;
>>> + 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 +775,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
>>> result = -errno;
>>> }
>>>
>>> +exit:
>>
>> Is goto+label better than a simple return statement?
>>
>
> In this case, maybe not.
>
>>> return result;
>>> }
>>>
>>>
>>
>> Do we need this patch for QEMU 2.0? For 32 bit systems, the image size
>> limit is 1000 TB, and that image would need 4 GB for the block cache in
>> memory. Are such image sizes used anywhere? For 64 bit systems, the
>> limit will be much higher.
>>
>
> I don't know what systems are in use in the wild. But since we
> allocate block cache to fit the entire cache in RAM currently, that
> does open us up to potentially allocating a lot of memory, based on
> what the image file header specifies.
>
> That is a reason to keep the maximum blocks_in_image size bounded to
> the size of 0x3fffffff. With an unbound blocks_in_image size (except
> to UINT32_MAX), the driver would potentially attempt to allocate 16GB
> of RAM, if qemu attempts to open a VDI image file with such a header.
Either we crash because of the 0x3fffffff limit, or we might crash
because a memory allocation fails (but it might also be successful). I
prefer this 2nd variant.
>
> Of course, if the VDI spec allows for image sizes > 1000TB, then maybe
> you are right and we should allow it, even if it means a lot of RAM
> allocation. I don't know.
>
> I think allowing blocks_in_images and block_size to be more variable
> is probably a good idea, but I think that if we are going to allow
> that, we should probably modify how we handle the block cache. And to
> add that support in would seem more in line with a feature addition.
>
I implemented most of the variable block handling. The only reason why I
did not activate it by default was that I had no real test cases.
Regards
Stefan
next prev parent reply other threads:[~2014-03-27 19:59 UTC|newest]
Thread overview: 104+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-26 12:05 [Qemu-devel] [PATCH for-2.0 00/47] block: image format input validation fixes Stefan Hajnoczi
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 01/47] qemu-iotests: add ./check -cloop support Stefan Hajnoczi
2014-03-26 19:25 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 02/47] qemu-iotests: add cloop input validation tests Stefan Hajnoczi
2014-03-26 19:31 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 03/47] block/cloop: validate block_size header field (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 19:38 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 04/47] block/cloop: prevent offsets_size integer overflow (CVE-2014-0143) Stefan Hajnoczi
2014-03-26 19:41 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 05/47] block/cloop: refuse images with huge offsets arrays (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 19:43 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 06/47] block/cloop: refuse images with bogus offsets (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 19:48 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 07/47] block/cloop: fix offsets[] size off-by-one Stefan Hajnoczi
2014-03-26 19:51 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 08/47] qemu-iotests: Support for bochs format Stefan Hajnoczi
2014-03-26 19:58 ` Max Reitz
2014-04-01 17:01 ` Kevin Wolf
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 09/47] bochs: Unify header structs and make them QEMU_PACKED Stefan Hajnoczi
2014-03-26 19:59 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 10/47] bochs: Use unsigned variables for offsets and sizes (CVE-2014-0147) Stefan Hajnoczi
2014-03-26 20:02 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 11/47] bochs: Check catalog_size header field (CVE-2014-0143) Stefan Hajnoczi
2014-03-26 20:09 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 12/47] bochs: Check extent_size header field (CVE-2014-0142) Stefan Hajnoczi
2014-03-26 20:13 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 13/47] bochs: Fix bitmap offset calculation Stefan Hajnoczi
2014-03-26 20:14 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 14/47] vpc/vhd: add bounds check for max_table_entries and block_size (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 20:15 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 15/47] vpc: Validate block size (CVE-2014-0142) Stefan Hajnoczi
2014-03-26 20:22 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 16/47] vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 18:21 ` Stefan Weil
2014-03-27 18:52 ` Jeff Cody
2014-03-27 19:58 ` Stefan Weil [this message]
2014-03-28 9:07 ` Stefan Hajnoczi
2014-03-28 12:52 ` Jeff Cody
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 17/47] vhdx: Bounds checking for block_size and logical_sector_size (CVE-2014-0148) Stefan Hajnoczi
2014-03-26 20:26 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 18/47] curl: check data size before memcpy to local buffer. (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 20:29 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 19/47] qcow2: Check header_length (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 20:40 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 20/47] qcow2: Check backing_file_offset (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 20:46 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 21/47] qcow2: Check refcount table size (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 20:50 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 22/47] qcow2: Validate refcount table offset Stefan Hajnoczi
2014-03-26 20:52 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 23/47] qcow2: Validate snapshot table offset/size (CVE-2014-0144) Stefan Hajnoczi
2014-03-26 20:59 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 24/47] qcow2: Validate active L1 table offset and size (CVE-2014-0144) Stefan Hajnoczi
2014-03-28 22:36 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 25/47] qcow2: Fix backing file name length check Stefan Hajnoczi
2014-03-28 22:39 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 26/47] qcow2: Don't rely on free_cluster_index in alloc_refcount_block() (CVE-2014-0147) Stefan Hajnoczi
2014-03-28 17:06 ` [Qemu-devel] [PATCH v2 " Stefan Hajnoczi
2014-03-28 22:51 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 27/47] qcow2: Avoid integer overflow in get_refcount (CVE-2014-0143) Stefan Hajnoczi
2014-03-28 22:58 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 28/47] qcow2: Check new refcount table size on growth Stefan Hajnoczi
2014-03-28 23:00 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 29/47] qcow2: Fix types in qcow2_alloc_clusters and alloc_clusters_noref Stefan Hajnoczi
2014-03-28 23:04 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 30/47] qcow2: Protect against some integer overflows in bdrv_check Stefan Hajnoczi
2014-03-28 23:06 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 31/47] qcow2: Fix new L1 table size check (CVE-2014-0143) Stefan Hajnoczi
2014-03-28 23:07 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 32/47] dmg: coding style and indentation cleanup Stefan Hajnoczi
2014-03-28 23:08 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 33/47] dmg: prevent out-of-bounds array access on terminator Stefan Hajnoczi
2014-03-28 23:10 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 34/47] dmg: drop broken bdrv_pread() loop Stefan Hajnoczi
2014-03-28 23:10 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 35/47] dmg: use appropriate types when reading chunks Stefan Hajnoczi
2014-03-28 23:10 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 36/47] dmg: sanitize chunk length and sectorcount (CVE-2014-0145) Stefan Hajnoczi
2014-03-28 23:11 ` Max Reitz
2014-03-26 12:05 ` [Qemu-devel] [PATCH for-2.0 37/47] dmg: use uint64_t consistently for sectors and lengths Stefan Hajnoczi
2014-03-28 23:11 ` Max Reitz
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 38/47] dmg: prevent chunk buffer overflow (CVE-2014-0145) Stefan Hajnoczi
2014-03-28 23:12 ` Max Reitz
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 39/47] block: vdi bounds check qemu-io tests Stefan Hajnoczi
2014-03-28 23:22 ` Max Reitz
2014-03-29 0:26 ` Jeff Cody
2014-03-31 7:12 ` Stefan Hajnoczi
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 40/47] block: Limit request size (CVE-2014-0143) Stefan Hajnoczi
2014-03-28 23:24 ` Max Reitz
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 41/47] qcow2: Fix copy_sectors() with VM state Stefan Hajnoczi
2014-03-28 23:33 ` Max Reitz
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 42/47] qcow2: Fix NULL dereference in qcow2_open() error path (CVE-2014-0146) Stefan Hajnoczi
2014-03-28 23:35 ` Max Reitz
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 43/47] qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp() (CVE-2014-0145) Stefan Hajnoczi
2014-03-28 23:38 ` Max Reitz
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 44/47] qcow2: Check maximum L1 size in qcow2_snapshot_load_tmp() (CVE-2014-0143) Stefan Hajnoczi
2014-03-28 23:39 ` Max Reitz
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 45/47] qcow2: Limit snapshot table size Stefan Hajnoczi
2014-03-28 23:41 ` Max Reitz
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 46/47] parallels: Fix catalog size integer overflow (CVE-2014-0143) Stefan Hajnoczi
2014-03-28 23:45 ` Max Reitz
2014-03-26 12:06 ` [Qemu-devel] [PATCH for-2.0 47/47] parallels: Sanity check for s->tracks (CVE-2014-0142) Stefan Hajnoczi
2014-03-28 23:46 ` Max Reitz
2014-04-01 13:49 ` [Qemu-devel] [PATCH for-2.0 00/47] block: image format input validation fixes Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=533482EE.2060609@weilnetz.de \
--to=sw@weilnetz.de \
--cc=jcody@redhat.com \
--cc=kwolf@redhat.com \
--cc=pmatouse@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-stable@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).