|
|
9ae3a8 |
From ec4d254830e3da2ebb1cd9fec16c407e5b644ca6 Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
Date: Tue, 25 Mar 2014 14:23:44 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 37/49] dmg: sanitize chunk length and sectorcount (CVE-2014-0145)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
Message-id: <1395753835-7591-38-git-send-email-kwolf@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: n/a
|
|
|
9ae3a8 |
O-Subject: [virt-devel] [EMBARGOED RHEL-7.0 qemu-kvm PATCH 37/48] dmg: sanitize chunk length and sectorcount (CVE-2014-0145)
|
|
|
9ae3a8 |
Bugzilla: 1079325
|
|
|
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 |
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1079325
|
|
|
9ae3a8 |
Upstream status: Embargoed
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Chunk length and sectorcount are used for decompression buffers as well
|
|
|
9ae3a8 |
as the bdrv_pread() count argument. Ensure that they have reasonable
|
|
|
9ae3a8 |
values so neither memory allocation nor conversion from uint64_t to int
|
|
|
9ae3a8 |
will cause problems.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
block/dmg.c | 24 ++++++++++++++++++++++++
|
|
|
9ae3a8 |
1 files changed, 24 insertions(+), 0 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/block/dmg.c b/block/dmg.c
|
|
|
9ae3a8 |
index f98c94d..ad253fe 100644
|
|
|
9ae3a8 |
--- a/block/dmg.c
|
|
|
9ae3a8 |
+++ b/block/dmg.c
|
|
|
9ae3a8 |
@@ -27,6 +27,14 @@
|
|
|
9ae3a8 |
#include "qemu/module.h"
|
|
|
9ae3a8 |
#include <zlib.h>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+enum {
|
|
|
9ae3a8 |
+ /* Limit chunk sizes to prevent unreasonable amounts of memory being used
|
|
|
9ae3a8 |
+ * or truncating when converting to 32-bit types
|
|
|
9ae3a8 |
+ */
|
|
|
9ae3a8 |
+ DMG_LENGTHS_MAX = 64 * 1024 * 1024, /* 64 MB */
|
|
|
9ae3a8 |
+ DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512,
|
|
|
9ae3a8 |
+};
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
typedef struct BDRVDMGState {
|
|
|
9ae3a8 |
CoMutex lock;
|
|
|
9ae3a8 |
/* each chunk contains a certain number of sectors,
|
|
|
9ae3a8 |
@@ -208,6 +216,14 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
offset += 8;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+ if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
|
|
|
9ae3a8 |
+ error_report("sector count %" PRIu64 " for chunk %u is "
|
|
|
9ae3a8 |
+ "larger than max (%u)",
|
|
|
9ae3a8 |
+ s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
|
|
|
9ae3a8 |
+ ret = -EINVAL;
|
|
|
9ae3a8 |
+ goto fail;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
ret = read_uint64(bs, offset, &s->offsets[i]);
|
|
|
9ae3a8 |
if (ret < 0) {
|
|
|
9ae3a8 |
goto fail;
|
|
|
9ae3a8 |
@@ -221,6 +237,14 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
offset += 8;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+ if (s->lengths[i] > DMG_LENGTHS_MAX) {
|
|
|
9ae3a8 |
+ error_report("length %" PRIu64 " for chunk %u is larger "
|
|
|
9ae3a8 |
+ "than max (%u)",
|
|
|
9ae3a8 |
+ s->lengths[i], i, DMG_LENGTHS_MAX);
|
|
|
9ae3a8 |
+ ret = -EINVAL;
|
|
|
9ae3a8 |
+ goto fail;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
if (s->lengths[i] > max_compressed_size) {
|
|
|
9ae3a8 |
max_compressed_size = s->lengths[i];
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.1
|
|
|
9ae3a8 |
|