qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp() (CVE-2014-0145)
authorKevin Wolf <kwolf@redhat.com>
Wed, 26 Mar 2014 12:06:05 +0000 (13:06 +0100)
committerStefan Hajnoczi <stefanha@redhat.com>
Tue, 1 Apr 2014 13:22:35 +0000 (15:22 +0200)
For the L1 table to loaded for an internal snapshot, the code allocated
only enough memory to hold the currently active L1 table. If the
snapshot's L1 table is actually larger than the current one, this leads
to a buffer overflow.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
block/qcow2-snapshot.c
tests/qemu-iotests/029
tests/qemu-iotests/029.out

index 87fbfe13a43ebf5c0085a7f84a2e77d920bd6ecb..715168e31ff1d1134e048c2b9848f24955114100 100644 (file)
@@ -680,7 +680,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
     sn = &s->snapshots[snapshot_index];
 
     /* Allocate and read in the snapshot's L1 table */
-    new_l1_bytes = s->l1_size * sizeof(uint64_t);
+    new_l1_bytes = sn->l1_size * sizeof(uint64_t);
     new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512));
 
     ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table, new_l1_bytes);
index 567e07160cad1abe86001fc0bba0e5e5ee1dbb98..fa46ace67b4a358a19709ea0eb9cd66ce0301d67 100755 (executable)
@@ -30,7 +30,8 @@ status=1      # failure is the default!
 
 _cleanup()
 {
-       _cleanup_test_img
+    rm -f $TEST_IMG.snap
+    _cleanup_test_img
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -44,6 +45,9 @@ _supported_fmt qcow2
 _supported_proto generic
 _supported_os Linux
 
+offset_size=24
+offset_l1_size=36
+
 echo
 echo Test loading internal snapshots where the L1 table of the snapshot
 echo is smaller than the current L1 table.
@@ -77,6 +81,18 @@ _make_test_img 64M
 _check_test_img
 
 
+echo
+echo "qcow2_snapshot_load_tmp() should take the L1 size from the snapshot"
+echo
+
+CLUSTER_SIZE=512
+_make_test_img 64M
+{ $QEMU_IMG snapshot -c foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_size" "\x00\x00\x00\x00\x00\x00\x02\x00"
+poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01"
+{ $QEMU_IMG convert -s foo $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
index 9029698a1cf213fd7a2d53ee04f0b984188ee6ed..ce0e64d24a1825abf2687714a9ddfcfe29550ef8 100644 (file)
@@ -20,4 +20,8 @@ wrote 4096/4096 bytes at offset 1099511627776
 read 4096/4096 bytes at offset 1099511627776
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 No errors were found on the image.
+
+qcow2_snapshot_load_tmp() should take the L1 size from the snapshot
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
 *** done