All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, stefanha@redhat.com, ppandit@redhat.com
Subject: [Qemu-devel] [PATCH 4/5] qcow1: Validate image size (CVE-2014-0223)
Date: Mon, 12 May 2014 15:04:10 +0200	[thread overview]
Message-ID: <1399899851-5641-5-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1399899851-5641-1-git-send-email-kwolf@redhat.com>

A huge image size could cause s->l1_size to overflow. Make sure that
images never require a L1 table larger than what fits in s->l1_size.

This cannot only cause unbounded allocations, but also the allocation of
a too small L1 table, resulting in out-of-bounds array accesses (both
reads and writes).

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow.c               | 16 ++++++++++++++--
 tests/qemu-iotests/092     |  9 +++++++++
 tests/qemu-iotests/092.out |  7 +++++++
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/block/qcow.c b/block/qcow.c
index e8038e5..3566c05 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -61,7 +61,7 @@ typedef struct BDRVQcowState {
     int cluster_sectors;
     int l2_bits;
     int l2_size;
-    int l1_size;
+    unsigned int l1_size;
     uint64_t cluster_offset_mask;
     uint64_t l1_table_offset;
     uint64_t *l1_table;
@@ -166,7 +166,19 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
 
     /* read the level 1 table */
     shift = s->cluster_bits + s->l2_bits;
-    s->l1_size = (header.size + (1LL << shift) - 1) >> shift;
+    if (header.size > UINT64_MAX - (1LL << shift)) {
+        error_setg(errp, "Image too large");
+        ret = -EINVAL;
+        goto fail;
+    } else {
+        uint64_t l1_size = (header.size + (1LL << shift) - 1) >> shift;
+        if (l1_size > INT_MAX / sizeof(uint64_t)) {
+            error_setg(errp, "Image too large");
+            ret = -EINVAL;
+            goto fail;
+        }
+        s->l1_size = l1_size;
+    }
 
     s->l1_table_offset = header.l1_table_offset;
     s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t));
diff --git a/tests/qemu-iotests/092 b/tests/qemu-iotests/092
index 2196cce..26a1324 100755
--- a/tests/qemu-iotests/092
+++ b/tests/qemu-iotests/092
@@ -43,6 +43,7 @@ _supported_fmt qcow
 _supported_proto generic
 _supported_os Linux
 
+offset_size=24
 offset_cluster_bits=32
 offset_l2_bits=33
 
@@ -64,6 +65,14 @@ poke_file "$TEST_IMG" "$offset_l2_bits" "\xff"
 poke_file "$TEST_IMG" "$offset_l2_bits" "\x1b"
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Invalid size =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_size" "\xee\xee\xee\xee\xee\xee\xee\xee"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_size" "\x7f\xff\xff\xff\xff\xff\xff\xff"
+{ $QEMU_IO -c "write 0 64M" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/092.out b/tests/qemu-iotests/092.out
index 45a7ac8..c3678a0 100644
--- a/tests/qemu-iotests/092.out
+++ b/tests/qemu-iotests/092.out
@@ -13,4 +13,11 @@ qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 an
 no file open, try 'help open'
 qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
 no file open, try 'help open'
+
+== Invalid size ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.qcow: Image too large
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow: Image too large
+no file open, try 'help open'
 *** done
-- 
1.8.3.1

  parent reply	other threads:[~2014-05-12 13:04 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-12 13:04 [Qemu-devel] [PATCH 0/5] qcow1: Input validation fixes Kevin Wolf
2014-05-12 13:04 ` [Qemu-devel] [PATCH 1/5] qcow1: Make padding in the header explicit Kevin Wolf
2014-05-12 14:39   ` Benoît Canet
2014-05-12 13:04 ` [Qemu-devel] [PATCH 2/5] qcow1: Check maximum cluster size Kevin Wolf
2014-05-12 15:00   ` Benoît Canet
2014-05-15 14:13     ` Kevin Wolf
2014-05-12 13:04 ` [Qemu-devel] [PATCH 3/5] qcow1: Validate L2 table size (CVE-2014-0222) Kevin Wolf
2014-05-12 15:09   ` Benoît Canet
2014-05-12 13:04 ` Kevin Wolf [this message]
2014-05-12 15:50   ` [Qemu-devel] [PATCH 4/5] qcow1: Validate image size (CVE-2014-0223) Benoît Canet
2014-05-12 16:43     ` Kevin Wolf
2014-05-12 17:04       ` Benoît Canet
2014-05-12 21:02         ` Benoît Canet
2014-05-13  8:41         ` Kevin Wolf
2014-05-12 13:04 ` [Qemu-devel] [PATCH 5/5] qcow1: Stricter backing file length check Kevin Wolf
2014-05-12 15:53   ` [Qemu-devel] [PATCH 5/5] qcow1: Stricter backing file length check* Benoît Canet
2014-05-13 13:08 ` [Qemu-devel] [PATCH 0/5] qcow1: Input validation fixes Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1399899851-5641-5-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=ppandit@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.