From: Jeff Cody Date: Wed, 26 Mar 2014 12:05:39 +0000 (+0100) Subject: vhdx: Bounds checking for block_size and logical_sector_size (CVE-2014-0148) X-Git-Tag: qemu-xen-4.4.3-rc1~35 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=e86cc068c2206a08b4552c513b0e3290ed681dd1;p=qemu-upstream-4.4-testing.git vhdx: Bounds checking for block_size and logical_sector_size (CVE-2014-0148) Other variables (e.g. sectors_per_block) are calculated using these variables, and if not range-checked illegal values could be obtained causing infinite loops and other potential issues when calculating BAT entries. The 1.00 VHDX spec requires BlockSize to be min 1MB, max 256MB. LogicalSectorSize is required to be either 512 or 4096 bytes. Reported-by: Kevin Wolf Signed-off-by: Jeff Cody Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- diff --git a/block/vhdx.c b/block/vhdx.c index e9704b1fd..36fc06c2c 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -627,12 +627,20 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s) le32_to_cpus(&s->logical_sector_size); le32_to_cpus(&s->physical_sector_size); - if (s->logical_sector_size == 0 || s->params.block_size == 0) { + if (s->params.block_size < VHDX_BLOCK_SIZE_MIN || + s->params.block_size > VHDX_BLOCK_SIZE_MAX) { ret = -EINVAL; goto exit; } - /* both block_size and sector_size are guaranteed powers of 2 */ + /* only 2 supported sector sizes */ + if (s->logical_sector_size != 512 && s->logical_sector_size != 4096) { + ret = -EINVAL; + goto exit; + } + + /* Both block_size and sector_size are guaranteed powers of 2, below. + Due to range checks above, s->sectors_per_block can never be < 256 */ s->sectors_per_block = s->params.block_size / s->logical_sector_size; s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) * (uint64_t)s->logical_sector_size / diff --git a/block/vhdx.h b/block/vhdx.h index fb687ed2d..77844e342 100644 --- a/block/vhdx.h +++ b/block/vhdx.h @@ -18,6 +18,11 @@ #ifndef BLOCK_VHDX_H #define BLOCK_VHDX_H +#define KiB (1 * 1024) +#define MiB (KiB * 1024) +#define GiB (MiB * 1024) +#define TiB ((uint64_t) GiB * 1024) + /* Structures and fields present in the VHDX file */ /* The header section has the following blocks, @@ -262,6 +267,8 @@ typedef struct QEMU_PACKED VHDXMetadataTableEntry { If set indicates a fixed size VHDX file */ #define VHDX_PARAMS_HAS_PARENT 0x02 /* has parent / backing file */ +#define VHDX_BLOCK_SIZE_MIN (1 * MiB) +#define VHDX_BLOCK_SIZE_MAX (256 * MiB) typedef struct QEMU_PACKED VHDXFileParameters { uint32_t block_size; /* size of each payload block, always power of 2, <= 256MB and >= 1MB. */