qemu/0158-qcow2-Limit-snapshot-t...

82 lines
2.8 KiB
Diff

From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:06:07 +0100
Subject: [PATCH] qcow2: Limit snapshot table size
Even with a limit of 64k snapshots, each snapshot could have a filename
and an ID with up to 64k, which would still lead to pretty large
allocations, which could potentially lead to qemu aborting. Limit the
total size of the snapshot table to an average of 1k per entry when
the limit of 64k snapshots is fully used. This should be plenty for any
reasonable user.
This also fixes potential integer overflows of s->snapshot_size.
Suggested-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 5dae6e30c531feb31eed99f9039b52bf70832ce3)
---
block/qcow2-snapshot.c | 15 ++++++++++++++-
block/qcow2.h | 4 ++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index d2c956c..5d3c0e6 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -116,8 +116,14 @@ int qcow2_read_snapshots(BlockDriverState *bs)
}
offset += name_size;
sn->name[name_size] = '\0';
+
+ if (offset - s->snapshots_offset > QCOW_MAX_SNAPSHOTS_SIZE) {
+ ret = -EFBIG;
+ goto fail;
+ }
}
+ assert(offset - s->snapshots_offset <= INT_MAX);
s->snapshots_size = offset - s->snapshots_offset;
return 0;
@@ -138,7 +144,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
uint32_t nb_snapshots;
uint64_t snapshots_offset;
} QEMU_PACKED header_data;
- int64_t offset, snapshots_offset;
+ int64_t offset, snapshots_offset = 0;
int ret;
/* compute the size of the snapshots */
@@ -150,7 +156,14 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
offset += sizeof(extra);
offset += strlen(sn->id_str);
offset += strlen(sn->name);
+
+ if (offset > QCOW_MAX_SNAPSHOTS_SIZE) {
+ ret = -EFBIG;
+ goto fail;
+ }
}
+
+ assert(offset <= INT_MAX);
snapshots_size = offset;
/* Allocate space for the new snapshot list */
diff --git a/block/qcow2.h b/block/qcow2.h
index 0912488..797c9d8 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -48,6 +48,10 @@
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
#define QCOW_MAX_L1_SIZE 0x2000000
+/* Allow for an average of 1k per snapshot table entry, should be plenty of
+ * space for snapshot names and IDs */
+#define QCOW_MAX_SNAPSHOTS_SIZE (1024 * QCOW_MAX_SNAPSHOTS)
+
/* indicate that the refcount of the referenced cluster is exactly one. */
#define QCOW_OFLAG_COPIED (1LL << 63)
/* indicate that the cluster is compressed (they never have the copied flag) */