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