From 72e671b52d93d8e1eb6f4e914bd8a29b907f6bd7 Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Tue, 25 Mar 2014 11:45:52 +0100 Subject: [PATCH 34/48] vhdx: Bounds checking for block_size and logical_sector_size (CVE-2014-0148) RH-Author: Kevin Wolf Message-id: <1395744364-16049-34-git-send-email-kwolf@redhat.com> Patchwork-id: n/a O-Subject: [EMBARGOED RHEL-6.6/6.5.z qemu-kvm PATCH v2 33/45] vhdx: Bounds checking for block_size and logical_sector_size (CVE-2014-0148) Bugzilla: 1079344 RH-Acked-by: Max Reitz RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Jeff Cody Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1079344 Upstream status: Embargoed 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 Picked some #defines for vhdx.h from upstream commit 3412f7b1 ('block: vhdx - add .bdrv_create() support') to make it build in RHEL 6. Signed-off-by: Kevin Wolf --- block/vhdx.c | 12 ++++++++++-- block/vhdx.h | 7 +++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/block/vhdx.c b/block/vhdx.c index a05eff4..da4b71e 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -628,12 +628,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 c3b64c6..de85f05 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. */ -- 1.7.1