mirror of https://github.com/xqemu/xqemu.git
vmdk: check granularity field in opening
Granularity is used to calculate the cluster size and allocate r/w buffer. Check the value from image before using it, so we don't abort() for unbounded memory allocation. Signed-off-by: Fam Zheng <famz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
ca6cbb657d
commit
8aa1331c09
40
block/vmdk.c
40
block/vmdk.c
|
@ -385,15 +385,22 @@ static int vmdk_parent_open(BlockDriverState *bs)
|
||||||
|
|
||||||
/* Create and append extent to the extent array. Return the added VmdkExtent
|
/* Create and append extent to the extent array. Return the added VmdkExtent
|
||||||
* address. return NULL if allocation failed. */
|
* address. return NULL if allocation failed. */
|
||||||
static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
|
static int vmdk_add_extent(BlockDriverState *bs,
|
||||||
BlockDriverState *file, bool flat, int64_t sectors,
|
BlockDriverState *file, bool flat, int64_t sectors,
|
||||||
int64_t l1_offset, int64_t l1_backup_offset,
|
int64_t l1_offset, int64_t l1_backup_offset,
|
||||||
uint32_t l1_size,
|
uint32_t l1_size,
|
||||||
int l2_size, unsigned int cluster_sectors)
|
int l2_size, uint64_t cluster_sectors,
|
||||||
|
VmdkExtent **new_extent)
|
||||||
{
|
{
|
||||||
VmdkExtent *extent;
|
VmdkExtent *extent;
|
||||||
BDRVVmdkState *s = bs->opaque;
|
BDRVVmdkState *s = bs->opaque;
|
||||||
|
|
||||||
|
if (cluster_sectors > 0x200000) {
|
||||||
|
/* 0x200000 * 512Bytes = 1GB for one cluster is unrealistic */
|
||||||
|
error_report("invalid granularity, image may be corrupt");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
s->extents = g_realloc(s->extents,
|
s->extents = g_realloc(s->extents,
|
||||||
(s->num_extents + 1) * sizeof(VmdkExtent));
|
(s->num_extents + 1) * sizeof(VmdkExtent));
|
||||||
extent = &s->extents[s->num_extents];
|
extent = &s->extents[s->num_extents];
|
||||||
|
@ -416,7 +423,10 @@ static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
|
||||||
extent->end_sector = extent->sectors;
|
extent->end_sector = extent->sectors;
|
||||||
}
|
}
|
||||||
bs->total_sectors = extent->end_sector;
|
bs->total_sectors = extent->end_sector;
|
||||||
return extent;
|
if (new_extent) {
|
||||||
|
*new_extent = extent;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
|
static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
|
||||||
|
@ -475,12 +485,17 @@ static int vmdk_open_vmdk3(BlockDriverState *bs,
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
extent = vmdk_add_extent(bs,
|
|
||||||
|
ret = vmdk_add_extent(bs,
|
||||||
bs->file, false,
|
bs->file, false,
|
||||||
le32_to_cpu(header.disk_sectors),
|
le32_to_cpu(header.disk_sectors),
|
||||||
le32_to_cpu(header.l1dir_offset) << 9,
|
le32_to_cpu(header.l1dir_offset) << 9,
|
||||||
0, 1 << 6, 1 << 9,
|
0, 1 << 6, 1 << 9,
|
||||||
le32_to_cpu(header.granularity));
|
le32_to_cpu(header.granularity),
|
||||||
|
&extent);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
ret = vmdk_init_tables(bs, extent);
|
ret = vmdk_init_tables(bs, extent);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* free extent allocated by vmdk_add_extent */
|
/* free extent allocated by vmdk_add_extent */
|
||||||
|
@ -580,13 +595,17 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||||
if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) {
|
if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) {
|
||||||
l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9;
|
l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9;
|
||||||
}
|
}
|
||||||
extent = vmdk_add_extent(bs, file, false,
|
ret = vmdk_add_extent(bs, file, false,
|
||||||
le64_to_cpu(header.capacity),
|
le64_to_cpu(header.capacity),
|
||||||
le64_to_cpu(header.gd_offset) << 9,
|
le64_to_cpu(header.gd_offset) << 9,
|
||||||
l1_backup_offset,
|
l1_backup_offset,
|
||||||
l1_size,
|
l1_size,
|
||||||
le32_to_cpu(header.num_gtes_per_gte),
|
le32_to_cpu(header.num_gtes_per_gte),
|
||||||
le64_to_cpu(header.granularity));
|
le64_to_cpu(header.granularity),
|
||||||
|
&extent);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
extent->compressed =
|
extent->compressed =
|
||||||
le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
|
le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
|
||||||
extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER;
|
extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER;
|
||||||
|
@ -702,8 +721,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
||||||
/* FLAT extent */
|
/* FLAT extent */
|
||||||
VmdkExtent *extent;
|
VmdkExtent *extent;
|
||||||
|
|
||||||
extent = vmdk_add_extent(bs, extent_file, true, sectors,
|
ret = vmdk_add_extent(bs, extent_file, true, sectors,
|
||||||
0, 0, 0, 0, sectors);
|
0, 0, 0, 0, sectors, &extent);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
extent->flat_start_offset = flat_offset << 9;
|
extent->flat_start_offset = flat_offset << 9;
|
||||||
} else if (!strcmp(type, "SPARSE")) {
|
} else if (!strcmp(type, "SPARSE")) {
|
||||||
/* SPARSE extent */
|
/* SPARSE extent */
|
||||||
|
|
|
@ -43,7 +43,13 @@ _supported_fmt vmdk
|
||||||
_supported_proto generic
|
_supported_proto generic
|
||||||
_supported_os Linux
|
_supported_os Linux
|
||||||
|
|
||||||
granularity_offset=16
|
granularity_offset=20
|
||||||
|
|
||||||
|
echo "=== Testing invalid granularity ==="
|
||||||
|
echo
|
||||||
|
_make_test_img 64M
|
||||||
|
poke_file "$TEST_IMG" "$granularity_offset" "\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||||
|
{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
|
||||||
|
|
||||||
# success, all done
|
# success, all done
|
||||||
echo "*** done"
|
echo "*** done"
|
||||||
|
|
|
@ -1,2 +1,8 @@
|
||||||
QA output created by 059
|
QA output created by 059
|
||||||
|
=== Testing invalid granularity ===
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||||
|
invalid granularity, image may be corrupt
|
||||||
|
qemu-io: can't open device TEST_DIR/t.vmdk
|
||||||
|
no file open, try 'help open'
|
||||||
*** done
|
*** done
|
||||||
|
|
Loading…
Reference in New Issue