eb5a2f
From 0867b2aac8b789d492af127b12437e526774b7cf Mon Sep 17 00:00:00 2001
eb5a2f
From: Kevin Wolf <kwolf@redhat.com>
eb5a2f
Date: Mon, 2 Jun 2014 13:54:45 +0200
eb5a2f
Subject: [PATCH 24/30] qcow1: Check maximum cluster size
eb5a2f
eb5a2f
RH-Author: Kevin Wolf <kwolf@redhat.com>
eb5a2f
Message-id: <1401717288-3918-4-git-send-email-kwolf@redhat.com>
eb5a2f
Patchwork-id: 59098
eb5a2f
O-Subject: [RHEL-7.1/7.0.z qemu-kvm PATCH 3/6] qcow1: Check maximum cluster size
eb5a2f
Bugzilla: 1097229
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
eb5a2f
Huge values for header.cluster_bits cause unbounded allocations (e.g.
eb5a2f
for s->cluster_cache) and crash qemu this way. Less huge values may
eb5a2f
survive those allocations, but can cause integer overflows later on.
eb5a2f
eb5a2f
The only cluster sizes that qemu can create are 4k (for standalone
eb5a2f
images) and 512 (for images with backing files), so we can limit it
eb5a2f
to 64k.
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
eb5a2f
Conflicts:
eb5a2f
	tests/qemu-iotests/group
eb5a2f
eb5a2f
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
eb5a2f
(cherry picked from commit 7159a45b2bf2dcb9f49f1e27d1d3d135a0247a2f)
eb5a2f
---
eb5a2f
 block/qcow.c               | 10 ++++++--
eb5a2f
 tests/qemu-iotests/092     | 63 ++++++++++++++++++++++++++++++++++++++++++++++
eb5a2f
 tests/qemu-iotests/092.out | 13 ++++++++++
eb5a2f
 tests/qemu-iotests/group   |  1 +
eb5a2f
 4 files changed, 85 insertions(+), 2 deletions(-)
eb5a2f
 create mode 100755 tests/qemu-iotests/092
eb5a2f
 create mode 100644 tests/qemu-iotests/092.out
eb5a2f
eb5a2f
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
eb5a2f
---
eb5a2f
 block/qcow.c               |   10 +++++-
eb5a2f
 tests/qemu-iotests/092     |   63 ++++++++++++++++++++++++++++++++++++++++++++
eb5a2f
 tests/qemu-iotests/092.out |   13 +++++++++
eb5a2f
 tests/qemu-iotests/group   |    1 +
eb5a2f
 4 files changed, 85 insertions(+), 2 deletions(-)
eb5a2f
 create mode 100755 tests/qemu-iotests/092
eb5a2f
 create mode 100644 tests/qemu-iotests/092.out
eb5a2f
eb5a2f
diff --git a/block/qcow.c b/block/qcow.c
eb5a2f
index 220ac04..2efe2fc 100644
eb5a2f
--- a/block/qcow.c
eb5a2f
+++ b/block/qcow.c
eb5a2f
@@ -126,11 +126,17 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
eb5a2f
         goto fail;
eb5a2f
     }
eb5a2f
 
eb5a2f
-    if (header.size <= 1 || header.cluster_bits < 9) {
eb5a2f
-        error_setg(errp, "invalid value in qcow header");
eb5a2f
+    if (header.size <= 1) {
eb5a2f
+        error_setg(errp, "Image size is too small (must be at least 2 bytes)");
eb5a2f
         ret = -EINVAL;
eb5a2f
         goto fail;
eb5a2f
     }
eb5a2f
+    if (header.cluster_bits < 9 || header.cluster_bits > 16) {
eb5a2f
+        error_setg(errp, "Cluster 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
new file mode 100755
eb5a2f
index 0000000..d060e6f
eb5a2f
--- /dev/null
eb5a2f
+++ b/tests/qemu-iotests/092
eb5a2f
@@ -0,0 +1,63 @@
eb5a2f
+#!/bin/bash
eb5a2f
+#
eb5a2f
+# qcow1 format input validation tests
eb5a2f
+#
eb5a2f
+# Copyright (C) 2014 Red Hat, Inc.
eb5a2f
+#
eb5a2f
+# This program is free software; you can redistribute it and/or modify
eb5a2f
+# it under the terms of the GNU General Public License as published by
eb5a2f
+# the Free Software Foundation; either version 2 of the License, or
eb5a2f
+# (at your option) any later version.
eb5a2f
+#
eb5a2f
+# This program is distributed in the hope that it will be useful,
eb5a2f
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
eb5a2f
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
eb5a2f
+# GNU General Public License for more details.
eb5a2f
+#
eb5a2f
+# You should have received a copy of the GNU General Public License
eb5a2f
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
eb5a2f
+#
eb5a2f
+
eb5a2f
+# creator
eb5a2f
+owner=kwolf@redhat.com
eb5a2f
+
eb5a2f
+seq=`basename $0`
eb5a2f
+echo "QA output created by $seq"
eb5a2f
+
eb5a2f
+here=`pwd`
eb5a2f
+tmp=/tmp/$$
eb5a2f
+status=1	# failure is the default!
eb5a2f
+
eb5a2f
+_cleanup()
eb5a2f
+{
eb5a2f
+    rm -f $TEST_IMG.snap
eb5a2f
+    _cleanup_test_img
eb5a2f
+}
eb5a2f
+trap "_cleanup; exit \$status" 0 1 2 3 15
eb5a2f
+
eb5a2f
+# get standard environment, filters and checks
eb5a2f
+. ./common.rc
eb5a2f
+. ./common.filter
eb5a2f
+
eb5a2f
+_supported_fmt qcow
eb5a2f
+_supported_proto generic
eb5a2f
+_supported_os Linux
eb5a2f
+
eb5a2f
+offset_cluster_bits=32
eb5a2f
+
eb5a2f
+echo
eb5a2f
+echo "== Invalid cluster size =="
eb5a2f
+_make_test_img 64M
eb5a2f
+poke_file "$TEST_IMG" "$offset_cluster_bits" "\xff"
eb5a2f
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
eb5a2f
+poke_file "$TEST_IMG" "$offset_cluster_bits" "\x1f"
eb5a2f
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
eb5a2f
+poke_file "$TEST_IMG" "$offset_cluster_bits" "\x08"
eb5a2f
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
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
+# success, all done
eb5a2f
+echo "*** done"
eb5a2f
+rm -f $seq.full
eb5a2f
+status=0
eb5a2f
diff --git a/tests/qemu-iotests/092.out b/tests/qemu-iotests/092.out
eb5a2f
new file mode 100644
eb5a2f
index 0000000..8bf8158
eb5a2f
--- /dev/null
eb5a2f
+++ b/tests/qemu-iotests/092.out
eb5a2f
@@ -0,0 +1,13 @@
eb5a2f
+QA output created by 092
eb5a2f
+
eb5a2f
+== Invalid cluster size ==
eb5a2f
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
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
+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
+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
+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
+*** done
eb5a2f
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
eb5a2f
index ad96fcf..d6d4a7f 100644
eb5a2f
--- a/tests/qemu-iotests/group
eb5a2f
+++ b/tests/qemu-iotests/group
eb5a2f
@@ -81,3 +81,4 @@
eb5a2f
 084 img auto
eb5a2f
 086 rw auto quick
eb5a2f
 088 rw auto
eb5a2f
+092 rw auto quick
eb5a2f
-- 
eb5a2f
1.7.1
eb5a2f