mirror of https://gitee.com/openkylin/qemu.git
qcow2: Prevent allocating refcount blocks at offset 0
Each entry in the qcow2 cache contains an offset field indicating the location of the data in the qcow2 image. If the offset is 0 then it means that the entry contains no data and is available to be used when needed. Because of that it is not possible to store in the cache the first cluster of the qcow2 image (offset = 0). This is not a problem because that cluster always contains the qcow2 header and we're not using this cache for that. However, if the qcow2 image is corrupted it can happen that we try to allocate a new refcount block at offset 0, triggering this assertion and crashing QEMU: qcow2_cache_entry_mark_dirty: Assertion `c->entries[i].offset != 0' failed This patch adds an explicit check for this scenario and a new test case. This problem was originally reported here: https://bugs.launchpad.net/qemu/+bug/1728615 Reported-by: R.Nageswara Sastry <nasastry@in.ibm.com> Signed-off-by: Alberto Garcia <berto@igalia.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Message-id: 92a2fadd10d58b423f269c1d1a309af161cdc73f.1509718618.git.berto@igalia.com Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
191b5fbfa6
commit
6bf45d59f9
|
@ -367,6 +367,13 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||||
return new_block;
|
return new_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we're allocating the block at offset 0 then something is wrong */
|
||||||
|
if (new_block == 0) {
|
||||||
|
qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid "
|
||||||
|
"allocation of refcount block at offset 0");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_ALLOC2
|
#ifdef DEBUG_ALLOC2
|
||||||
fprintf(stderr, "qcow2: Allocate refcount block %d for %" PRIx64
|
fprintf(stderr, "qcow2: Allocate refcount block %d for %" PRIx64
|
||||||
" at %" PRIx64 "\n",
|
" at %" PRIx64 "\n",
|
||||||
|
|
|
@ -242,6 +242,17 @@ poke_file "$TEST_IMG" "$(($l2_offset+8))" "\x80\x00\x00\x00\x00\x06\x2a\x00"
|
||||||
# Should emit two error messages
|
# Should emit two error messages
|
||||||
$QEMU_IO -c "discard 0 64k" -c "read 64k 64k" "$TEST_IMG" | _filter_qemu_io
|
$QEMU_IO -c "discard 0 64k" -c "read 64k 64k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Testing empty refcount table with valid L1 and L2 tables ==="
|
||||||
|
echo
|
||||||
|
_make_test_img 64M
|
||||||
|
$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
poke_file "$TEST_IMG" "$rt_offset" "\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
# Since the first data cluster is already allocated this triggers an
|
||||||
|
# allocation with an explicit offset (using qcow2_alloc_clusters_at())
|
||||||
|
# causing a refcount block to be allocated at offset 0
|
||||||
|
$QEMU_IO -c "write 0 128k" "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
# success, all done
|
# success, all done
|
||||||
echo "*** done"
|
echo "*** done"
|
||||||
rm -f $seq.full
|
rm -f $seq.full
|
||||||
|
|
|
@ -181,4 +181,12 @@ qcow2: Marking image as corrupt: Cluster allocation offset 0x62a00 unaligned (L2
|
||||||
discard 65536/65536 bytes at offset 0
|
discard 65536/65536 bytes at offset 0
|
||||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
read failed: Input/output error
|
read failed: Input/output error
|
||||||
|
|
||||||
|
=== Testing empty refcount table with valid L1 and L2 tables ===
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||||
|
wrote 65536/65536 bytes at offset 0
|
||||||
|
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
qcow2: Marking image as corrupt: Preventing invalid allocation of refcount block at offset 0; further corruption events will be suppressed
|
||||||
|
write failed: Input/output error
|
||||||
*** done
|
*** done
|
||||||
|
|
Loading…
Reference in New Issue