diff mbox

[3/3] block: Catch integer overflow in bdrv_rw_co()

Message ID 1397653710-22971-4-git-send-email-kwolf@redhat.com
State New
Headers show

Commit Message

Kevin Wolf April 16, 2014, 1:08 p.m. UTC
Insanely large requests could cause an integer overflow in
bdrv_rw_co() while converting sectors to bytes. This patch catches the
problem and returns an error (if we hadn't overflown the integer here,
bdrv_check_byte_request() would have rejected the request, so we're not
breaking anything that was supposed to work before).

We actually do have a test case that triggers behaviour where we
accidentally let such a request pass, so that it would return success,
but read 0 bytes instead of the requested 4 GB. It fails now like it
should.

If the vdi block driver wants to be able to deal with huge images, it
can't read the whole block bitmap at once into memory like it does
today, but needs to use a metadata cache like qcow2 does.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c                    | 4 ++++
 tests/qemu-iotests/084.out | 5 +----
 2 files changed, 5 insertions(+), 4 deletions(-)

Comments

Max Reitz April 16, 2014, 10:23 p.m. UTC | #1
On 16.04.2014 15:08, Kevin Wolf wrote:
> Insanely large requests could cause an integer overflow in
> bdrv_rw_co() while converting sectors to bytes. This patch catches the
> problem and returns an error (if we hadn't overflown the integer here,
> bdrv_check_byte_request() would have rejected the request, so we're not
> breaking anything that was supposed to work before).
>
> We actually do have a test case that triggers behaviour where we
> accidentally let such a request pass, so that it would return success,
> but read 0 bytes instead of the requested 4 GB. It fails now like it
> should.
>
> If the vdi block driver wants to be able to deal with huge images, it
> can't read the whole block bitmap at once into memory like it does
> today, but needs to use a metadata cache like qcow2 does.
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>   block.c                    | 4 ++++
>   tests/qemu-iotests/084.out | 5 +----
>   2 files changed, 5 insertions(+), 4 deletions(-)

Maybe we should add some comment to test 084, as I can easily understand 
someone getting confused as why such a test now catching something 
practically unrelated to VDI there. Or we should just leave the output 
as it is, making the test deliberately fail.

The fix itself is correct, though. Requests exceeding INT_MAX bytes 
aren't supported in other places as well (right now, discards come to my 
mind), so it should be fine to reject them here as well.

Max
diff mbox

Patch

diff --git a/block.c b/block.c
index bcf9dc9..d268ece 100644
--- a/block.c
+++ b/block.c
@@ -2698,6 +2698,10 @@  static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
         .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
     };
 
+    if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
+        return -EINVAL;
+    }
+
     qemu_iovec_init_external(&qiov, &iov, 1);
     return bdrv_prwv_co(bs, sector_num << BDRV_SECTOR_BITS,
                         &qiov, is_write, flags);
diff --git a/tests/qemu-iotests/084.out b/tests/qemu-iotests/084.out
index e681924..c7120d9 100644
--- a/tests/qemu-iotests/084.out
+++ b/tests/qemu-iotests/084.out
@@ -4,10 +4,7 @@  QA output created by 084
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
 Test 1: Maximum size (1024 TB):
-image: TEST_DIR/t.IMGFMT
-file format: IMGFMT
-virtual size: 1024T (1125899905794048 bytes)
-cluster_size: 1048576
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'TEST_DIR/t.IMGFMT': Invalid argument
 
 Test 2: Size too large (1024TB + 1)
 qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported VDI image size (size is 0x3fffffff10000, max supported is 0x3fffffff00000)