Re: [Qemu-devel] [PATCH v2 11/16] qcow2: Keep track of the snapshot table length

2019-08-19 Thread Eric Blake
On 8/19/19 1:55 PM, Max Reitz wrote:
> When repairing the snapshot table, we truncate entries that have too
> much extra data.  This frees up space that we do not have to count
> towards the snapshot table size.
> 
> Signed-off-by: Max Reitz 
> ---
>  block/qcow2-snapshot.c | 14 +-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [PATCH v2 11/16] qcow2: Keep track of the snapshot table length

2019-08-19 Thread Max Reitz
When repairing the snapshot table, we truncate entries that have too
much extra data.  This frees up space that we do not have to count
towards the snapshot table size.

Signed-off-by: Max Reitz 
---
 block/qcow2-snapshot.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 53dc1635ec..582eb3386a 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -68,6 +68,7 @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool 
repair,
 QCowSnapshot *sn;
 int i, id_str_size, name_size;
 int64_t offset;
+uint64_t table_length = 0;
 int ret;
 
 if (!s->nb_snapshots) {
@@ -82,6 +83,8 @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool 
repair,
 for(i = 0; i < s->nb_snapshots; i++) {
 bool truncate_unknown_extra_data = false;
 
+table_length = ROUND_UP(table_length, 8);
+
 /* Read statically sized part of the snapshot header */
 offset = ROUND_UP(offset, 8);
 ret = bdrv_pread(bs->file, offset, , sizeof(h));
@@ -184,7 +187,16 @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, 
bool repair,
 offset += name_size;
 sn->name[name_size] = '\0';
 
-if (offset - s->snapshots_offset > QCOW_MAX_SNAPSHOTS_SIZE) {
+/* Note that the extra data may have been truncated */
+table_length += sizeof(h) + sn->extra_data_size + id_str_size +
+name_size;
+if (!repair) {
+assert(table_length == offset - s->snapshots_offset);
+}
+
+if (table_length > QCOW_MAX_SNAPSHOTS_SIZE ||
+offset - s->snapshots_offset > INT_MAX)
+{
 ret = -EFBIG;
 error_setg(errp, "Snapshot table is too big");
 goto fail;
-- 
2.21.0