7452f5d212
Fix regression in CVE backport that affects openstack (thanks lbezdick)
83 lines
2.9 KiB
Diff
83 lines
2.9 KiB
Diff
From 51b8dca866a1b77a9803ee3b56e059f8e7795dd8 Mon Sep 17 00:00:00 2001
|
|
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) */
|