peterdelevoryas / rpms / qemu

Forked from rpms/qemu 2 years ago
Clone

Blame 0104-qcow1-Validate-image-size-CVE-2014-0223.patch

12cd54
From 92e1dd206a3bb8ddbea0ece22bc05e9446a69436 Mon Sep 17 00:00:00 2001
12cd54
From: Kevin Wolf <kwolf@redhat.com>
12cd54
Date: Thu, 8 May 2014 13:08:20 +0200
12cd54
Subject: [PATCH] qcow1: Validate image size (CVE-2014-0223)
12cd54
12cd54
A huge image size could cause s->l1_size to overflow. Make sure that
12cd54
images never require a L1 table larger than what fits in s->l1_size.
12cd54
12cd54
This cannot only cause unbounded allocations, but also the allocation of
12cd54
a too small L1 table, resulting in out-of-bounds array accesses (both
12cd54
reads and writes).
12cd54
12cd54
Cc: qemu-stable@nongnu.org
12cd54
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12cd54
(cherry picked from commit 46485de0cb357b57373e1ca895adedf1f3ed46ec)
12cd54
12cd54
Conflicts:
12cd54
	tests/qemu-iotests/092
12cd54
	tests/qemu-iotests/092.out
12cd54
---
12cd54
 block/qcow.c | 16 ++++++++++++++--
12cd54
 1 file changed, 14 insertions(+), 2 deletions(-)
12cd54
12cd54
diff --git a/block/qcow.c b/block/qcow.c
12cd54
index 8718ca5..f9cb009 100644
12cd54
--- a/block/qcow.c
12cd54
+++ b/block/qcow.c
12cd54
@@ -61,7 +61,7 @@ typedef struct BDRVQcowState {
12cd54
     int cluster_sectors;
12cd54
     int l2_bits;
12cd54
     int l2_size;
12cd54
-    int l1_size;
12cd54
+    unsigned int l1_size;
12cd54
     uint64_t cluster_offset_mask;
12cd54
     uint64_t l1_table_offset;
12cd54
     uint64_t *l1_table;
12cd54
@@ -165,7 +165,19 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
12cd54
 
12cd54
     /* read the level 1 table */
12cd54
     shift = s->cluster_bits + s->l2_bits;
12cd54
-    s->l1_size = (header.size + (1LL << shift) - 1) >> shift;
12cd54
+    if (header.size > UINT64_MAX - (1LL << shift)) {
12cd54
+        error_setg(errp, "Image too large");
12cd54
+        ret = -EINVAL;
12cd54
+        goto fail;
12cd54
+    } else {
12cd54
+        uint64_t l1_size = (header.size + (1LL << shift) - 1) >> shift;
12cd54
+        if (l1_size > INT_MAX / sizeof(uint64_t)) {
12cd54
+            error_setg(errp, "Image too large");
12cd54
+            ret = -EINVAL;
12cd54
+            goto fail;
12cd54
+        }
12cd54
+        s->l1_size = l1_size;
12cd54
+    }
12cd54
 
12cd54
     s->l1_table_offset = header.l1_table_offset;
12cd54
     s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t));