Am 02.09.2019 um 17:24 hat Peter Lieven geschrieben:
qemu is currently not able to detect truncated vhdx image files.
Add a basic check if all allocated blocks are reachable at open and
report all errors during bdrv_co_check.
Signed-off-by: Peter Lieven <address@hidden>
---
V2: - add error reporting [Kevin]
- use bdrv_getlength instead of bdrv_get_allocated_file_size [Kevin]
- factor out BAT entry check and add error reporting for region
overlaps
- already check on vhdx_open
block/vhdx.c | 85 +++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 68 insertions(+), 17 deletions(-)
diff --git a/block/vhdx.c b/block/vhdx.c
index 6a09d0a55c..6afba5e8c2 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -24,6 +24,7 @@
#include "qemu/option.h"
#include "qemu/crc32c.h"
#include "qemu/bswap.h"
+#include "qemu/error-report.h"
#include "vhdx.h"
#include "migration/blocker.h"
#include "qemu/uuid.h"
@@ -235,6 +236,9 @@ static int vhdx_region_check(BDRVVHDXState *s, uint64_t
start, uint64_t length)
end = start + length;
QLIST_FOREACH(r, &s->regions, entries) {
if (!((start >= r->end) || (end <= r->start))) {
+ error_report("VHDX region %" PRIu64 "-%" PRIu64 " overlaps with "
+ "region %" PRIu64 "-%." PRIu64, start, end, r->start,
+ r->end);
ret = -EINVAL;
goto exit;
}
@@ -877,6 +881,60 @@ static void vhdx_calc_bat_entries(BDRVVHDXState *s)
}
+static int vhdx_check_bat_entries(BlockDriverState *bs, int *errcnt)
+{
+ BDRVVHDXState *s = bs->opaque;
+ int64_t image_file_size = bdrv_getlength(bs->file->bs);
+ uint64_t payblocks = s->chunk_ratio;
+ int i, ret = 0;
bdrv_getlength() can fail. It's probably better to error out immediately
instead of reporting that every BAT entry is > -1.
+ for (i = 0; i < s->bat_entries; i++) {
s->bat_entries is uint32_t, so i should probably be the same.
+ if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
+ PAYLOAD_BLOCK_FULLY_PRESENT) {
+ /*
+ * Check if fully allocated BAT entries do not reside after
+ * end of the image file.
+ */
+ if ((s->bat[i] & VHDX_BAT_FILE_OFF_MASK) + s->block_size >
+ image_file_size) {
Didn't we want to introduce an overflow check before making this check?
Something like if (bat_offset > UINT64_MAX - s->block_size)?