f3a92caa76
CVE-2014-0150: virtio-net: buffer overflow in virtio_net_handle_mac() function (bz #1086775, bz #1078846) CVE-2013-4544: vmxnet3: bounds checking buffer overrun (bz #1087513, bz #1087522) CVE-2014-2894: out of bounds buffer accesses, guest triggerable via IDE SMART (bz #1087981, bz #1087971)
76 lines
2.8 KiB
Diff
76 lines
2.8 KiB
Diff
From af26019bf167d71fc3a8e5d46865a4c53d58e976 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
Date: Wed, 26 Mar 2014 13:05:29 +0100
|
|
Subject: [PATCH] block/cloop: fix offsets[] size off-by-one
|
|
|
|
cloop stores the number of compressed blocks in the n_blocks header
|
|
field. The file actually contains n_blocks + 1 offsets, where the extra
|
|
offset is the end-of-file offset.
|
|
|
|
The following line in cloop_read_block() results in an out-of-bounds
|
|
offsets[] access:
|
|
|
|
uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
|
|
|
|
This patch allocates and loads the extra offset so that
|
|
cloop_read_block() works correctly when the last block is accessed.
|
|
|
|
Notice that we must free s->offsets[] unconditionally now since there is
|
|
always an end-of-file offset.
|
|
|
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
(cherry picked from commit 42d43d35d907579179a39c924d169da924786f65)
|
|
|
|
Conflicts:
|
|
tests/qemu-iotests/075
|
|
tests/qemu-iotests/075.out
|
|
---
|
|
block/cloop.c | 12 +++++-------
|
|
1 file changed, 5 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/block/cloop.c b/block/cloop.c
|
|
index 5c9c085..b28aae1 100644
|
|
--- a/block/cloop.c
|
|
+++ b/block/cloop.c
|
|
@@ -98,14 +98,14 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags)
|
|
s->n_blocks = be32_to_cpu(s->n_blocks);
|
|
|
|
/* read offsets */
|
|
- if (s->n_blocks > UINT32_MAX / sizeof(uint64_t)) {
|
|
+ if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
|
|
/* Prevent integer overflow */
|
|
fprintf(stderr, "n_blocks %u must be %zu or less",
|
|
s->n_blocks,
|
|
- UINT32_MAX / sizeof(uint64_t));
|
|
+ (UINT32_MAX - 1) / sizeof(uint64_t));
|
|
return -EINVAL;
|
|
}
|
|
- offsets_size = s->n_blocks * sizeof(uint64_t);
|
|
+ offsets_size = (s->n_blocks + 1) * sizeof(uint64_t);
|
|
if (offsets_size > 512 * 1024 * 1024) {
|
|
/* Prevent ridiculous offsets_size which causes memory allocation to
|
|
* fail or overflows bdrv_pread() size. In practice the 512 MB
|
|
@@ -122,7 +122,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags)
|
|
goto fail;
|
|
}
|
|
|
|
- for(i=0;i<s->n_blocks;i++) {
|
|
+ for (i = 0; i < s->n_blocks + 1; i++) {
|
|
uint64_t size;
|
|
|
|
s->offsets[i] = be64_to_cpu(s->offsets[i]);
|
|
@@ -242,9 +242,7 @@ static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num,
|
|
static void cloop_close(BlockDriverState *bs)
|
|
{
|
|
BDRVCloopState *s = bs->opaque;
|
|
- if (s->n_blocks > 0) {
|
|
- g_free(s->offsets);
|
|
- }
|
|
+ g_free(s->offsets);
|
|
g_free(s->compressed_block);
|
|
g_free(s->uncompressed_block);
|
|
inflateEnd(&s->zstream);
|