From: Stefan Hajnoczi Date: Thu, 5 Mar 2015 11:27:26 +0000 (+0000) Subject: dmg: sanitize chunk length and sectorcount (CVE-2014-0145) X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=ab689a89ec47b2e1c964c57bea7da68f8ddf89fd;p=qemu-upstream-4.3-testing.git dmg: sanitize chunk length and sectorcount (CVE-2014-0145) Chunk length and sectorcount are used for decompression buffers as well as the bdrv_pread() count argument. Ensure that they have reasonable values so neither memory allocation nor conversion from uint64_t to int will cause problems. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi Signed-off-by: Stefano Stabellini --- diff --git a/block/dmg.c b/block/dmg.c index dc3b50754..1311f6ba6 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -27,6 +27,14 @@ #include "module.h" #include +enum { + /* Limit chunk sizes to prevent unreasonable amounts of memory being used + * or truncating when converting to 32-bit types + */ + DMG_LENGTHS_MAX = 64 * 1024 * 1024, /* 64 MB */ + DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512, +}; + typedef struct BDRVDMGState { CoMutex lock; /* each chunk contains a certain number of sectors, @@ -186,12 +194,26 @@ static int dmg_open(BlockDriverState *bs, int flags) s->sectorcounts[i] = read_off(bs, offset); offset += 8; + if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) { + error_report("sector count %" PRIu64 " for chunk %u is " + "larger than max (%u)", + s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX); + goto fail; + } + s->offsets[i] = last_in_offset+read_off(bs, offset); offset += 8; s->lengths[i] = read_off(bs, offset); offset += 8; + if (s->lengths[i] > DMG_LENGTHS_MAX) { + error_report("length %" PRIu64 " for chunk %u is larger " + "than max (%u)", + s->lengths[i], i, DMG_LENGTHS_MAX); + goto fail; + } + update_max_chunk_size(s, i, &max_compressed_size, &max_sectors_per_chunk); }