9ae3a8
From 1235b1580890e2a034bb24f89a89311d296d2622 Mon Sep 17 00:00:00 2001
9ae3a8
From: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Date: Tue, 25 Mar 2014 14:23:51 +0100
9ae3a8
Subject: [PATCH 44/49] qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp() (CVE-2014-0145)
9ae3a8
9ae3a8
RH-Author: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Message-id: <1395753835-7591-45-git-send-email-kwolf@redhat.com>
9ae3a8
Patchwork-id: n/a
9ae3a8
O-Subject: [virt-devel] [EMBARGOED RHEL-7.0 qemu-kvm PATCH 44/48] qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp() (CVE-2014-0145)
9ae3a8
Bugzilla: 1079325
9ae3a8
RH-Acked-by: Jeff Cody <jcody@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
9ae3a8
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1079325
9ae3a8
Upstream status: Embargoed
9ae3a8
9ae3a8
For the L1 table to loaded for an internal snapshot, the code allocated
9ae3a8
only enough memory to hold the currently active L1 table. If the
9ae3a8
snapshot's L1 table is actually larger than the current one, this leads
9ae3a8
to a buffer overflow.
9ae3a8
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
---
9ae3a8
 block/qcow2-snapshot.c     |    2 +-
9ae3a8
 tests/qemu-iotests/029     |   18 +++++++++++++++++-
9ae3a8
 tests/qemu-iotests/029.out |    4 ++++
9ae3a8
 3 files changed, 22 insertions(+), 2 deletions(-)
9ae3a8
9ae3a8
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
9ae3a8
index 5d73506..b29f7bd 100644
9ae3a8
--- a/block/qcow2-snapshot.c
9ae3a8
+++ b/block/qcow2-snapshot.c
9ae3a8
@@ -635,7 +635,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name)
9ae3a8
     sn = &s->snapshots[snapshot_index];
9ae3a8
 
9ae3a8
     /* Allocate and read in the snapshot's L1 table */
9ae3a8
-    new_l1_bytes = s->l1_size * sizeof(uint64_t);
9ae3a8
+    new_l1_bytes = sn->l1_size * sizeof(uint64_t);
9ae3a8
     new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512));
9ae3a8
 
9ae3a8
     ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table, new_l1_bytes);
9ae3a8
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
9ae3a8
index 567e071..fa46ace 100755
9ae3a8
--- a/tests/qemu-iotests/029
9ae3a8
+++ b/tests/qemu-iotests/029
9ae3a8
@@ -30,7 +30,8 @@ status=1	# failure is the default!
9ae3a8
 
9ae3a8
 _cleanup()
9ae3a8
 {
9ae3a8
-	_cleanup_test_img
9ae3a8
+    rm -f $TEST_IMG.snap
9ae3a8
+    _cleanup_test_img
9ae3a8
 }
9ae3a8
 trap "_cleanup; exit \$status" 0 1 2 3 15
9ae3a8
 
9ae3a8
@@ -44,6 +45,9 @@ _supported_fmt qcow2
9ae3a8
 _supported_proto generic
9ae3a8
 _supported_os Linux
9ae3a8
 
9ae3a8
+offset_size=24
9ae3a8
+offset_l1_size=36
9ae3a8
+
9ae3a8
 echo
9ae3a8
 echo Test loading internal snapshots where the L1 table of the snapshot
9ae3a8
 echo is smaller than the current L1 table.
9ae3a8
@@ -77,6 +81,18 @@ _make_test_img 64M
9ae3a8
 _check_test_img
9ae3a8
 
9ae3a8
 
9ae3a8
+echo
9ae3a8
+echo "qcow2_snapshot_load_tmp() should take the L1 size from the snapshot"
9ae3a8
+echo
9ae3a8
+
9ae3a8
+CLUSTER_SIZE=512
9ae3a8
+_make_test_img 64M
9ae3a8
+{ $QEMU_IMG snapshot -c foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
9ae3a8
+poke_file "$TEST_IMG" "$offset_size" "\x00\x00\x00\x00\x00\x00\x02\x00"
9ae3a8
+poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01"
9ae3a8
+{ $QEMU_IMG convert -s foo $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_qemu_io | _filter_testdir
9ae3a8
+
9ae3a8
+
9ae3a8
 # success, all done
9ae3a8
 echo "*** done"
9ae3a8
 rm -f $seq.full
9ae3a8
diff --git a/tests/qemu-iotests/029.out b/tests/qemu-iotests/029.out
9ae3a8
index 9029698..ce0e64d 100644
9ae3a8
--- a/tests/qemu-iotests/029.out
9ae3a8
+++ b/tests/qemu-iotests/029.out
9ae3a8
@@ -20,4 +20,8 @@ wrote 4096/4096 bytes at offset 1099511627776
9ae3a8
 read 4096/4096 bytes at offset 1099511627776
9ae3a8
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
9ae3a8
 No errors were found on the image.
9ae3a8
+
9ae3a8
+qcow2_snapshot_load_tmp() should take the L1 size from the snapshot
9ae3a8
+
9ae3a8
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
9ae3a8
 *** done
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8