1369de9828
CVE-2014-3689 vmware_vga: insufficient parameter validation in rectangle functions (bz #1153038, bz #1153035)
149 lines
4.1 KiB
Diff
149 lines
4.1 KiB
Diff
From: Kevin Wolf <kwolf@redhat.com>
|
|
Date: Wed, 26 Mar 2014 13:05:45 +0100
|
|
Subject: [PATCH] qcow2: Validate snapshot table offset/size (CVE-2014-0144)
|
|
|
|
This avoid unbounded memory allocation and fixes a potential buffer
|
|
overflow on 32 bit hosts.
|
|
|
|
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 ce48f2f441ca98885267af6fd636a7cb804ee646)
|
|
|
|
Conflicts:
|
|
tests/qemu-iotests/080
|
|
tests/qemu-iotests/080.out
|
|
---
|
|
block/qcow2-snapshot.c | 29 ++++-------------------------
|
|
block/qcow2.c | 15 +++++++++++++++
|
|
block/qcow2.h | 29 ++++++++++++++++++++++++++++-
|
|
3 files changed, 47 insertions(+), 26 deletions(-)
|
|
|
|
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
|
|
index ae33b45..eb80438 100644
|
|
--- a/block/qcow2-snapshot.c
|
|
+++ b/block/qcow2-snapshot.c
|
|
@@ -26,31 +26,6 @@
|
|
#include "block/block_int.h"
|
|
#include "block/qcow2.h"
|
|
|
|
-typedef struct QEMU_PACKED QCowSnapshotHeader {
|
|
- /* header is 8 byte aligned */
|
|
- uint64_t l1_table_offset;
|
|
-
|
|
- uint32_t l1_size;
|
|
- uint16_t id_str_size;
|
|
- uint16_t name_size;
|
|
-
|
|
- uint32_t date_sec;
|
|
- uint32_t date_nsec;
|
|
-
|
|
- uint64_t vm_clock_nsec;
|
|
-
|
|
- uint32_t vm_state_size;
|
|
- uint32_t extra_data_size; /* for extension */
|
|
- /* extra data follows */
|
|
- /* id_str follows */
|
|
- /* name follows */
|
|
-} QCowSnapshotHeader;
|
|
-
|
|
-typedef struct QEMU_PACKED QCowSnapshotExtraData {
|
|
- uint64_t vm_state_size_large;
|
|
- uint64_t disk_size;
|
|
-} QCowSnapshotExtraData;
|
|
-
|
|
void qcow2_free_snapshots(BlockDriverState *bs)
|
|
{
|
|
BDRVQcowState *s = bs->opaque;
|
|
@@ -326,6 +301,10 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
|
uint64_t *l1_table = NULL;
|
|
int64_t l1_table_offset;
|
|
|
|
+ if (s->nb_snapshots >= QCOW_MAX_SNAPSHOTS) {
|
|
+ return -EFBIG;
|
|
+ }
|
|
+
|
|
memset(sn, 0, sizeof(*sn));
|
|
|
|
/* Generate an ID if it wasn't passed */
|
|
diff --git a/block/qcow2.c b/block/qcow2.c
|
|
index db35ffe..43e2db1 100644
|
|
--- a/block/qcow2.c
|
|
+++ b/block/qcow2.c
|
|
@@ -501,6 +501,21 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
|
|
goto fail;
|
|
}
|
|
|
|
+ /* Snapshot table offset/length */
|
|
+ if (header.nb_snapshots > QCOW_MAX_SNAPSHOTS) {
|
|
+ fprintf(stderr, "Too many snapshots");
|
|
+ ret = -EINVAL;
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ ret = validate_table_offset(bs, header.snapshots_offset,
|
|
+ header.nb_snapshots,
|
|
+ sizeof(QCowSnapshotHeader));
|
|
+ if (ret < 0) {
|
|
+ fprintf(stderr, "Invalid snapshot table offset");
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
s->snapshots_offset = header.snapshots_offset;
|
|
s->nb_snapshots = header.nb_snapshots;
|
|
|
|
diff --git a/block/qcow2.h b/block/qcow2.h
|
|
index da61d18..1e1294c 100644
|
|
--- a/block/qcow2.h
|
|
+++ b/block/qcow2.h
|
|
@@ -38,6 +38,7 @@
|
|
#define QCOW_CRYPT_AES 1
|
|
|
|
#define QCOW_MAX_CRYPT_CLUSTERS 32
|
|
+#define QCOW_MAX_SNAPSHOTS 65536
|
|
|
|
/* indicate that the refcount of the referenced cluster is exactly one. */
|
|
#define QCOW_OFLAG_COPIED (1LL << 63)
|
|
@@ -88,6 +89,32 @@ typedef struct QCowHeader {
|
|
uint32_t header_length;
|
|
} QCowHeader;
|
|
|
|
+typedef struct QEMU_PACKED QCowSnapshotHeader {
|
|
+ /* header is 8 byte aligned */
|
|
+ uint64_t l1_table_offset;
|
|
+
|
|
+ uint32_t l1_size;
|
|
+ uint16_t id_str_size;
|
|
+ uint16_t name_size;
|
|
+
|
|
+ uint32_t date_sec;
|
|
+ uint32_t date_nsec;
|
|
+
|
|
+ uint64_t vm_clock_nsec;
|
|
+
|
|
+ uint32_t vm_state_size;
|
|
+ uint32_t extra_data_size; /* for extension */
|
|
+ /* extra data follows */
|
|
+ /* id_str follows */
|
|
+ /* name follows */
|
|
+} QCowSnapshotHeader;
|
|
+
|
|
+typedef struct QEMU_PACKED QCowSnapshotExtraData {
|
|
+ uint64_t vm_state_size_large;
|
|
+ uint64_t disk_size;
|
|
+} QCowSnapshotExtraData;
|
|
+
|
|
+
|
|
typedef struct QCowSnapshot {
|
|
uint64_t l1_table_offset;
|
|
uint32_t l1_size;
|
|
@@ -190,7 +217,7 @@ typedef struct BDRVQcowState {
|
|
AES_KEY aes_decrypt_key;
|
|
uint64_t snapshots_offset;
|
|
int snapshots_size;
|
|
- int nb_snapshots;
|
|
+ unsigned int nb_snapshots;
|
|
QCowSnapshot *snapshots;
|
|
|
|
int flags;
|