yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
958e1b
From 6a7dafce7c4fb8e13e331efb301baedffce08e3f Mon Sep 17 00:00:00 2001
eb5a2f
From: Kevin Wolf <kwolf@redhat.com>
eb5a2f
Date: Mon, 2 Jun 2014 13:54:46 +0200
958e1b
Subject: [PATCH 29/31] qcow1: Validate L2 table size (CVE-2014-0222)
eb5a2f
eb5a2f
RH-Author: Kevin Wolf <kwolf@redhat.com>
eb5a2f
Message-id: <1401717288-3918-5-git-send-email-kwolf@redhat.com>
eb5a2f
Patchwork-id: 59099
eb5a2f
O-Subject: [RHEL-7.1/7.0.z qemu-kvm PATCH 4/6] qcow1: Validate L2 table size (CVE-2014-0222)
958e1b
Bugzilla: 1097229 1097230
eb5a2f
RH-Acked-by: Max Reitz <mreitz@redhat.com>
eb5a2f
RH-Acked-by: Fam Zheng <famz@redhat.com>
eb5a2f
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
eb5a2f
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
eb5a2f
958e1b
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1097230
958e1b
eb5a2f
Too large L2 table sizes cause unbounded allocations. Images actually
eb5a2f
created by qemu-img only have 512 byte or 4k L2 tables.
eb5a2f
eb5a2f
To keep things consistent with cluster sizes, allow ranges between 512
eb5a2f
bytes and 64k (in fact, down to 1 entry = 8 bytes is technically
eb5a2f
working, but L2 table sizes smaller than a cluster don't make a lot of
eb5a2f
sense).
eb5a2f
eb5a2f
This also means that the number of bytes on the virtual disk that are
eb5a2f
described by the same L2 table is limited to at most 8k * 64k or 2^29,
eb5a2f
preventively avoiding any integer overflows.
eb5a2f
eb5a2f
Cc: qemu-stable@nongnu.org
eb5a2f
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
eb5a2f
Reviewed-by: Benoit Canet <benoit@irqsave.net>
eb5a2f
(cherry picked from commit 42eb58179b3b215bb507da3262b682b8a2ec10b5)
eb5a2f
---
eb5a2f
 block/qcow.c               |  8 ++++++++
eb5a2f
 tests/qemu-iotests/092     | 15 +++++++++++++++
eb5a2f
 tests/qemu-iotests/092.out | 11 +++++++++++
eb5a2f
 3 files changed, 34 insertions(+)
eb5a2f
eb5a2f
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
eb5a2f
---
eb5a2f
 block/qcow.c               |    8 ++++++++
eb5a2f
 tests/qemu-iotests/092     |   15 +++++++++++++++
eb5a2f
 tests/qemu-iotests/092.out |   11 +++++++++++
eb5a2f
 3 files changed, 34 insertions(+), 0 deletions(-)
eb5a2f
eb5a2f
diff --git a/block/qcow.c b/block/qcow.c
eb5a2f
index 2efe2fc..f266701 100644
eb5a2f
--- a/block/qcow.c
eb5a2f
+++ b/block/qcow.c
eb5a2f
@@ -137,6 +137,14 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
eb5a2f
         goto fail;
eb5a2f
     }
eb5a2f
 
eb5a2f
+    /* l2_bits specifies number of entries; storing a uint64_t in each entry,
eb5a2f
+     * so bytes = num_entries << 3. */
eb5a2f
+    if (header.l2_bits < 9 - 3 || header.l2_bits > 16 - 3) {
eb5a2f
+        error_setg(errp, "L2 table size must be between 512 and 64k");
eb5a2f
+        ret = -EINVAL;
eb5a2f
+        goto fail;
eb5a2f
+    }
eb5a2f
+
eb5a2f
     if (header.crypt_method > QCOW_CRYPT_AES) {
eb5a2f
         error_setg(errp, "invalid encryption method in qcow header");
eb5a2f
         ret = -EINVAL;
eb5a2f
diff --git a/tests/qemu-iotests/092 b/tests/qemu-iotests/092
eb5a2f
index d060e6f..fb8bacc 100755
eb5a2f
--- a/tests/qemu-iotests/092
eb5a2f
+++ b/tests/qemu-iotests/092
eb5a2f
@@ -44,6 +44,7 @@ _supported_proto generic
eb5a2f
 _supported_os Linux
eb5a2f
 
eb5a2f
 offset_cluster_bits=32
eb5a2f
+offset_l2_bits=33
eb5a2f
 
eb5a2f
 echo
eb5a2f
 echo "== Invalid cluster size =="
eb5a2f
@@ -57,6 +58,20 @@ poke_file "$TEST_IMG" "$offset_cluster_bits" "\x08"
eb5a2f
 poke_file "$TEST_IMG" "$offset_cluster_bits" "\x11"
eb5a2f
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
eb5a2f
 
eb5a2f
+echo
eb5a2f
+echo "== Invalid L2 table size =="
eb5a2f
+_make_test_img 64M
eb5a2f
+poke_file "$TEST_IMG" "$offset_l2_bits" "\xff"
eb5a2f
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
eb5a2f
+poke_file "$TEST_IMG" "$offset_l2_bits" "\x05"
eb5a2f
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
eb5a2f
+poke_file "$TEST_IMG" "$offset_l2_bits" "\x0e"
eb5a2f
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
eb5a2f
+
eb5a2f
+# 1 << 0x1b = 2^31 / L2_CACHE_SIZE
eb5a2f
+poke_file "$TEST_IMG" "$offset_l2_bits" "\x1b"
eb5a2f
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
eb5a2f
+
eb5a2f
 # success, all done
eb5a2f
 echo "*** done"
eb5a2f
 rm -f $seq.full
eb5a2f
diff --git a/tests/qemu-iotests/092.out b/tests/qemu-iotests/092.out
eb5a2f
index 8bf8158..73918b3 100644
eb5a2f
--- a/tests/qemu-iotests/092.out
eb5a2f
+++ b/tests/qemu-iotests/092.out
eb5a2f
@@ -10,4 +10,15 @@ qemu-io: can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and
eb5a2f
 no file open, try 'help open'
eb5a2f
 qemu-io: can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
eb5a2f
 no file open, try 'help open'
eb5a2f
+
eb5a2f
+== Invalid L2 table size ==
eb5a2f
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
eb5a2f
+qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
eb5a2f
+no file open, try 'help open'
eb5a2f
+qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
eb5a2f
+no file open, try 'help open'
eb5a2f
+qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
eb5a2f
+no file open, try 'help open'
eb5a2f
+qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
eb5a2f
+no file open, try 'help open'
eb5a2f
 *** done
eb5a2f
-- 
eb5a2f
1.7.1
eb5a2f