0a122b
From 38b7ffbe3a1fa62f4d5177a3a572aa1c9abb1963 Mon Sep 17 00:00:00 2001
0a122b
From: Kevin Wolf <kwolf@redhat.com>
0a122b
Date: Tue, 25 Mar 2014 14:23:33 +0100
0a122b
Subject: [PATCH 26/49] qcow2: Fix backing file name length check
0a122b
0a122b
RH-Author: Kevin Wolf <kwolf@redhat.com>
0a122b
Message-id: <1395753835-7591-27-git-send-email-kwolf@redhat.com>
0a122b
Patchwork-id: n/a
0a122b
O-Subject: [virt-devel] [EMBARGOED RHEL-7.0 qemu-kvm PATCH 26/48] qcow2: Fix backing file name length check
0a122b
Bugzilla: 1066691
0a122b
RH-Acked-by: Jeff Cody <jcody@redhat.com>
0a122b
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
0a122b
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
0a122b
0a122b
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1066691
0a122b
Upstream status: Series embargoed
0a122b
0a122b
len could become negative and would pass the check then. Nothing bad
0a122b
happened because bdrv_pread() happens to return an error for negative
0a122b
length values, but make variables for sizes unsigned anyway.
0a122b
0a122b
This patch also changes the behaviour to error out on invalid lengths
0a122b
instead of silently truncating it to 1023.
0a122b
0a122b
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
0a122b
---
0a122b
 block/qcow2.c              |    9 ++++++---
0a122b
 tests/qemu-iotests/080     |    8 ++++++++
0a122b
 tests/qemu-iotests/080.out |    5 +++++
0a122b
 3 files changed, 19 insertions(+), 3 deletions(-)
0a122b
0a122b
diff --git a/block/qcow2.c b/block/qcow2.c
0a122b
index 8be82f0..a8ad9e1 100644
0a122b
--- a/block/qcow2.c
0a122b
+++ b/block/qcow2.c
0a122b
@@ -445,7 +445,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
0a122b
                       Error **errp)
0a122b
 {
0a122b
     BDRVQcowState *s = bs->opaque;
0a122b
-    int len, i, ret = 0;
0a122b
+    unsigned int len, i;
0a122b
+    int ret = 0;
0a122b
     QCowHeader header;
0a122b
     QemuOpts *opts;
0a122b
     Error *local_err = NULL;
0a122b
@@ -720,8 +721,10 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
0a122b
     /* read the backing file name */
0a122b
     if (header.backing_file_offset != 0) {
0a122b
         len = header.backing_file_size;
0a122b
-        if (len > 1023) {
0a122b
-            len = 1023;
0a122b
+        if (len > MIN(1023, s->cluster_size - header.backing_file_offset)) {
0a122b
+            error_setg(errp, "Backing file name too long");
0a122b
+            ret = -EINVAL;
0a122b
+            goto fail;
0a122b
         }
0a122b
         ret = bdrv_pread(bs->file, header.backing_file_offset,
0a122b
                          bs->backing_file, len);
0a122b
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
0a122b
index 7255b6c..f3091a9 100755
0a122b
--- a/tests/qemu-iotests/080
0a122b
+++ b/tests/qemu-iotests/080
0a122b
@@ -45,6 +45,7 @@ _supported_os Linux
0a122b
 header_size=104
0a122b
 
0a122b
 offset_backing_file_offset=8
0a122b
+offset_backing_file_size=16
0a122b
 offset_l1_size=36
0a122b
 offset_l1_table_offset=40
0a122b
 offset_refcount_table_offset=48
0a122b
@@ -135,6 +136,13 @@ poke_file "$TEST_IMG" "$offset_l1_table_offset" "\x12\x34\x56\x78\x90\xab\xcd\xe
0a122b
 poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01"
0a122b
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
0a122b
 
0a122b
+echo
0a122b
+echo "== Invalid backing file size =="
0a122b
+_make_test_img 64M
0a122b
+poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x10\x00"
0a122b
+poke_file "$TEST_IMG" "$offset_backing_file_size" "\xff\xff\xff\xff"
0a122b
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
0a122b
+
0a122b
 # success, all done
0a122b
 echo "*** done"
0a122b
 rm -f $seq.full
0a122b
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
0a122b
index 4ec2545..8103211 100644
0a122b
--- a/tests/qemu-iotests/080.out
0a122b
+++ b/tests/qemu-iotests/080.out
0a122b
@@ -58,4 +58,9 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
0a122b
 no file open, try 'help open'
0a122b
 qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
0a122b
 no file open, try 'help open'
0a122b
+
0a122b
+== Invalid backing file size ==
0a122b
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
0a122b
+qemu-io: can't open device TEST_DIR/t.qcow2: Backing file name too long
0a122b
+no file open, try 'help open'
0a122b
 *** done
0a122b
-- 
0a122b
1.7.1
0a122b