9ae3a8
From 197c8b66cc0b7cc239075b4c86b0f118194e198a Mon Sep 17 00:00:00 2001
9ae3a8
From: Max Reitz <mreitz@redhat.com>
9ae3a8
Date: Sat, 13 Jun 2015 16:22:28 +0200
9ae3a8
Subject: [PATCH 34/42] qcow2: Fix header extension size check
9ae3a8
9ae3a8
Message-id: <1434212556-3927-35-git-send-email-mreitz@redhat.com>
9ae3a8
Patchwork-id: 66053
9ae3a8
O-Subject: [RHEL-7.2 qemu-kvm PATCH 34/42] qcow2: Fix header extension size check
9ae3a8
Bugzilla: 1129893
9ae3a8
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
9ae3a8
RH-Acked-by: Fam Zheng <famz@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
9ae3a8
From: Kevin Wolf <kwolf@redhat.com>
9ae3a8
9ae3a8
BZ: 1129893
9ae3a8
9ae3a8
After reading the extension header, offset is incremented, but not
9ae3a8
checked against end_offset any more. This way an integer overflow could
9ae3a8
happen when checking whether the extension end is within the allowed
9ae3a8
range, effectively disabling the check.
9ae3a8
9ae3a8
This patch adds the missing check and a test case for it.
9ae3a8
9ae3a8
Cc: qemu-stable@nongnu.org
9ae3a8
Reported-by: Max Reitz <mreitz@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9ae3a8
Message-id: 1416935562-7760-2-git-send-email-kwolf@redhat.com
9ae3a8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit 2ebafc854d109ff09b66fb4dd62c2c53fc29754a)
9ae3a8
9ae3a8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 block/qcow2.c              | 2 +-
9ae3a8
 tests/qemu-iotests/080     | 2 ++
9ae3a8
 tests/qemu-iotests/080.out | 2 ++
9ae3a8
 3 files changed, 5 insertions(+), 1 deletion(-)
9ae3a8
9ae3a8
diff --git a/block/qcow2.c b/block/qcow2.c
9ae3a8
index 4e60077..991c41f 100644
9ae3a8
--- a/block/qcow2.c
9ae3a8
+++ b/block/qcow2.c
9ae3a8
@@ -116,7 +116,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
9ae3a8
 #ifdef DEBUG_EXT
9ae3a8
         printf("ext.magic = 0x%x\n", ext.magic);
9ae3a8
 #endif
9ae3a8
-        if (ext.len > end_offset - offset) {
9ae3a8
+        if (offset > end_offset || ext.len > end_offset - offset) {
9ae3a8
             error_setg(errp, "Header extension too large");
9ae3a8
             return -EINVAL;
9ae3a8
         }
9ae3a8
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
9ae3a8
index 6b3a3e7..b9f9630 100755
9ae3a8
--- a/tests/qemu-iotests/080
9ae3a8
+++ b/tests/qemu-iotests/080
9ae3a8
@@ -78,6 +78,8 @@ poke_file "$TEST_IMG" "$offset_backing_file_offset" "\xff\xff\xff\xff\xff\xff\xf
9ae3a8
 poke_file "$TEST_IMG" "$offset_ext_magic" "\x12\x34\x56\x78"
9ae3a8
 poke_file "$TEST_IMG" "$offset_ext_size" "\x7f\xff\xff\xff"
9ae3a8
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
9ae3a8
+poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x$(printf %x $offset_ext_size)"
9ae3a8
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
9ae3a8
 poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x00"
9ae3a8
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
9ae3a8
 
9ae3a8
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
9ae3a8
index 1fa0672..b7db555 100644
9ae3a8
--- a/tests/qemu-iotests/080.out
9ae3a8
+++ b/tests/qemu-iotests/080.out
9ae3a8
@@ -13,6 +13,8 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset
9ae3a8
 no file open, try 'help open'
9ae3a8
 qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large
9ae3a8
 no file open, try 'help open'
9ae3a8
+qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large
9ae3a8
+no file open, try 'help open'
9ae3a8
 
9ae3a8
 == Huge refcount table size ==
9ae3a8
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8