|
|
9ae3a8 |
From 427c0839e73f5bb1b3b0fa33afd4a9e5ea3eb34b Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
Date: Tue, 25 Mar 2014 14:23:53 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 46/49] qcow2: Limit snapshot table size
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
Message-id: <1395753835-7591-47-git-send-email-kwolf@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: n/a
|
|
|
9ae3a8 |
O-Subject: [virt-devel] [EMBARGOED RHEL-7.0 qemu-kvm PATCH 46/48] qcow2: Limit snapshot table size
|
|
|
9ae3a8 |
Bugzilla: 1066691
|
|
|
9ae3a8 |
RH-Acked-by: Jeff Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1066691
|
|
|
9ae3a8 |
Upstream status: Series embargoed
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Even with a limit of 64k snapshots, each snapshot could have a filename
|
|
|
9ae3a8 |
and an ID with up to 64k, which would still lead to pretty large
|
|
|
9ae3a8 |
allocations, which could potentially lead to qemu aborting. Limit the
|
|
|
9ae3a8 |
total size of the snapshot table to an average of 1k per entry when
|
|
|
9ae3a8 |
the limit of 64k snapshots is fully used. This should be plenty for any
|
|
|
9ae3a8 |
reasonable user.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
This also fixes potential integer overflows of s->snapshot_size.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Suggested-by: Max Reitz <mreitz@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
block/qcow2-snapshot.c | 13 +++++++++++++
|
|
|
9ae3a8 |
block/qcow2.h | 4 ++++
|
|
|
9ae3a8 |
2 files changed, 17 insertions(+), 0 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
|
|
|
9ae3a8 |
index 626a8d4..84481be 100644
|
|
|
9ae3a8 |
--- a/block/qcow2-snapshot.c
|
|
|
9ae3a8 |
+++ b/block/qcow2-snapshot.c
|
|
|
9ae3a8 |
@@ -116,8 +116,14 @@ int qcow2_read_snapshots(BlockDriverState *bs)
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
offset += name_size;
|
|
|
9ae3a8 |
sn->name[name_size] = '\0';
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ if (offset - s->snapshots_offset > QCOW_MAX_SNAPSHOTS_SIZE) {
|
|
|
9ae3a8 |
+ ret = -EFBIG;
|
|
|
9ae3a8 |
+ goto fail;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+ assert(offset - s->snapshots_offset <= INT_MAX);
|
|
|
9ae3a8 |
s->snapshots_size = offset - s->snapshots_offset;
|
|
|
9ae3a8 |
return 0;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
@@ -150,7 +156,14 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
|
|
9ae3a8 |
offset += sizeof(extra);
|
|
|
9ae3a8 |
offset += strlen(sn->id_str);
|
|
|
9ae3a8 |
offset += strlen(sn->name);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ if (offset > QCOW_MAX_SNAPSHOTS_SIZE) {
|
|
|
9ae3a8 |
+ ret = -EFBIG;
|
|
|
9ae3a8 |
+ goto fail;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ assert(offset <= INT_MAX);
|
|
|
9ae3a8 |
snapshots_size = offset;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
/* Allocate space for the new snapshot list */
|
|
|
9ae3a8 |
diff --git a/block/qcow2.h b/block/qcow2.h
|
|
|
9ae3a8 |
index 87e256a..1cc1ef0 100644
|
|
|
9ae3a8 |
--- a/block/qcow2.h
|
|
|
9ae3a8 |
+++ b/block/qcow2.h
|
|
|
9ae3a8 |
@@ -48,6 +48,10 @@
|
|
|
9ae3a8 |
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
|
|
|
9ae3a8 |
#define QCOW_MAX_L1_SIZE 0x2000000
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+/* Allow for an average of 1k per snapshot table entry, should be plenty of
|
|
|
9ae3a8 |
+ * space for snapshot names and IDs */
|
|
|
9ae3a8 |
+#define QCOW_MAX_SNAPSHOTS_SIZE (1024 * QCOW_MAX_SNAPSHOTS)
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
/* indicate that the refcount of the referenced cluster is exactly one. */
|
|
|
9ae3a8 |
#define QCOW_OFLAG_COPIED (1LL << 63)
|
|
|
9ae3a8 |
/* indicate that the cluster is compressed (they never have the copied flag) */
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.1
|
|
|
9ae3a8 |
|