From 2d2d5cb5719024e47226e0c39138e9e99c20788d Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Tue, 25 Mar 2014 11:45:35 +0100
Subject: [PATCH 17/48] block/cloop: validate block_size header field (CVE-2014-0144)

RH-Author: Kevin Wolf <kwolf@redhat.com>
Message-id: <1395744364-16049-17-git-send-email-kwolf@redhat.com>
Patchwork-id: n/a
O-Subject: [EMBARGOED RHEL-6.6/6.5.z qemu-kvm PATCH v2 16/45]
           block/cloop: validate block_size header field (CVE-2014-0144)
Bugzilla: 1079453
RH-Acked-by: Max Reitz <mreitz@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Acked-by: Jeff Cody <jcody@redhat.com>

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1079453
Upstream status: Embargoed

Avoid unbounded s->uncompressed_block memory allocation by checking that
the block_size header field has a reasonable value.  Also enforce the
assumption that the value is a non-zero multiple of 512.

These constraints conform to cloop 2.639's code so we accept existing
image files.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>

Conflicts:
	tests/qemu-iotests/075
	tests/qemu-iotests/075.out

qerror_report() doesn't take a format string like error_setg() (it does
use a format string for the JSON representation, but we want to use
QERR_GENERIC_ERROR there), so changed error messages to static strings
for RHEL 6.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/cloop.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/block/cloop.c b/block/cloop.c
index 775f8a9..9caf7f0 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -26,6 +26,9 @@
 #include "module.h"
 #include <zlib.h>
 
+/* Maximum compressed block size */
+#define MAX_BLOCK_SIZE (64 * 1024 * 1024)
+
 typedef struct BDRVCloopState {
     CoMutex lock;
     uint32_t block_size;
@@ -63,6 +66,24 @@ static int cloop_open(BlockDriverState *bs, int flags)
         goto cloop_close;
     }
     s->block_size = be32_to_cpu(s->block_size);
+    if (s->block_size % 512) {
+        qerror_report(QERR_GENERIC_ERROR,
+                      "block_size must be a multiple of 512");
+        return -EINVAL;
+    }
+    if (s->block_size == 0) {
+        qerror_report(QERR_GENERIC_ERROR, "block_size cannot be zero");
+        return -EINVAL;
+    }
+
+    /* cloop's create_compressed_fs.c warns about block sizes beyond 256 KB but
+     * we can accept more.  Prevent ridiculous values like 4 GB - 1 since we
+     * need a buffer this big.
+     */
+    if (s->block_size > MAX_BLOCK_SIZE) {
+        qerror_report(QERR_GENERIC_ERROR, "block_size too large");
+        return -EINVAL;
+    }
 
     if (bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4) < 4) {
         goto cloop_close;
-- 
1.7.1

