7452f5d
From 87e8497708f3aec3f065aed5096b4ac32b01f17e Mon Sep 17 00:00:00 2001
f3a92ca
From: Kevin Wolf <kwolf@redhat.com>
f3a92ca
Date: Wed, 26 Mar 2014 13:06:05 +0100
f3a92ca
Subject: [PATCH] qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp()
f3a92ca
 (CVE-2014-0145)
f3a92ca
f3a92ca
For the L1 table to loaded for an internal snapshot, the code allocated
f3a92ca
only enough memory to hold the currently active L1 table. If the
f3a92ca
snapshot's L1 table is actually larger than the current one, this leads
f3a92ca
to a buffer overflow.
f3a92ca
f3a92ca
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
f3a92ca
Reviewed-by: Max Reitz <mreitz@redhat.com>
f3a92ca
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
f3a92ca
(cherry picked from commit c05e4667be91b46ab42b5a11babf8e84d476cc6b)
f3a92ca
---
f3a92ca
 block/qcow2-snapshot.c     |  2 +-
f3a92ca
 tests/qemu-iotests/029     | 18 +++++++++++++++++-
f3a92ca
 tests/qemu-iotests/029.out |  4 ++++
f3a92ca
 3 files changed, 22 insertions(+), 2 deletions(-)
f3a92ca
f3a92ca
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
f3a92ca
index eb80438..dc8736a 100644
f3a92ca
--- a/block/qcow2-snapshot.c
f3a92ca
+++ b/block/qcow2-snapshot.c
f3a92ca
@@ -622,7 +622,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name)
f3a92ca
     sn = &s->snapshots[snapshot_index];
f3a92ca
 
f3a92ca
     /* Allocate and read in the snapshot's L1 table */
f3a92ca
-    new_l1_bytes = s->l1_size * sizeof(uint64_t);
f3a92ca
+    new_l1_bytes = sn->l1_size * sizeof(uint64_t);
f3a92ca
     new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512));
f3a92ca
 
f3a92ca
     ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table, new_l1_bytes);
f3a92ca
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
f3a92ca
index 478fd96..dfb5726 100755
f3a92ca
--- a/tests/qemu-iotests/029
f3a92ca
+++ b/tests/qemu-iotests/029
f3a92ca
@@ -30,7 +30,8 @@ status=1	# failure is the default!
f3a92ca
 
f3a92ca
 _cleanup()
f3a92ca
 {
f3a92ca
-	_cleanup_test_img
f3a92ca
+    rm -f $TEST_IMG.snap
f3a92ca
+    _cleanup_test_img
f3a92ca
 }
f3a92ca
 trap "_cleanup; exit \$status" 0 1 2 3 15
f3a92ca
 
f3a92ca
@@ -44,6 +45,9 @@ _supported_fmt qcow2
f3a92ca
 _supported_proto generic
f3a92ca
 _supported_os Linux
f3a92ca
 
f3a92ca
+offset_size=24
f3a92ca
+offset_l1_size=36
f3a92ca
+
f3a92ca
 echo
f3a92ca
 echo Test loading internal snapshots where the L1 table of the snapshot
f3a92ca
 echo is smaller than the current L1 table.
f3a92ca
@@ -77,6 +81,18 @@ _make_test_img 64M
f3a92ca
 _check_test_img
f3a92ca
 
f3a92ca
 
f3a92ca
+echo
f3a92ca
+echo "qcow2_snapshot_load_tmp() should take the L1 size from the snapshot"
f3a92ca
+echo
f3a92ca
+
f3a92ca
+CLUSTER_SIZE=512
f3a92ca
+_make_test_img 64M
f3a92ca
+{ $QEMU_IMG snapshot -c foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
f3a92ca
+poke_file "$TEST_IMG" "$offset_size" "\x00\x00\x00\x00\x00\x00\x02\x00"
f3a92ca
+poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01"
f3a92ca
+{ $QEMU_IMG convert -s foo $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_qemu_io | _filter_testdir
f3a92ca
+
f3a92ca
+
f3a92ca
 # success, all done
f3a92ca
 echo "*** done"
f3a92ca
 rm -f $seq.full
f3a92ca
diff --git a/tests/qemu-iotests/029.out b/tests/qemu-iotests/029.out
f3a92ca
index 9029698..ce0e64d 100644
f3a92ca
--- a/tests/qemu-iotests/029.out
f3a92ca
+++ b/tests/qemu-iotests/029.out
f3a92ca
@@ -20,4 +20,8 @@ wrote 4096/4096 bytes at offset 1099511627776
f3a92ca
 read 4096/4096 bytes at offset 1099511627776
f3a92ca
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
f3a92ca
 No errors were found on the image.
f3a92ca
+
f3a92ca
+qcow2_snapshot_load_tmp() should take the L1 size from the snapshot
f3a92ca
+
f3a92ca
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
f3a92ca
 *** done