From 47f73da0a7d36e399eaa353d93afce90de9b599d Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Mar 2014 13:05:23 +0100 Subject: qemu-iotests: add ./check -cloop support Add the cloop block driver to qemu-iotests. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/common | 7 +++++++ tests/qemu-iotests/common.rc | 3 +++ 2 files changed, 10 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index 5795358..37e3bed 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -137,6 +137,7 @@ common options check options -raw test raw (default) -cow test cow + -cloop test cloop -qcow test qcow -qcow2 test qcow2 -qed test qed @@ -178,6 +179,12 @@ testlist options xpand=false ;; + -cloop) + IMGFMT=cloop + IMGFMT_GENERIC=false + xpand=false + ;; + -qcow) IMGFMT=qcow xpand=false diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 881079b..7f00883 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -364,6 +364,9 @@ _fail() # _supported_fmt() { + # "generic" is suitable for most image formats. For some formats it doesn't + # work, however (most notably read-only formats), so they can opt out by + # setting IMGFMT_GENERIC to false. for f; do if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then return -- cgit v1.1 From 05560fcebb1528f4354f6f24d1eb8cdbcdf2c4b2 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Mar 2014 13:05:24 +0100 Subject: qemu-iotests: add cloop input validation tests Add a cloop format-specific test case. Later patches add tests for input validation to the script. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/075 | 53 +++++++++++++++++++++ tests/qemu-iotests/075.out | 6 +++ tests/qemu-iotests/group | 1 + .../sample_images/simple-pattern.cloop.bz2 | Bin 0 -> 488 bytes 4 files changed, 60 insertions(+) create mode 100755 tests/qemu-iotests/075 create mode 100644 tests/qemu-iotests/075.out create mode 100644 tests/qemu-iotests/sample_images/simple-pattern.cloop.bz2 (limited to 'tests') diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075 new file mode 100755 index 0000000..88ae8bb --- /dev/null +++ b/tests/qemu-iotests/075 @@ -0,0 +1,53 @@ +#!/bin/bash +# +# cloop format input validation tests +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=stefanha@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt cloop +_supported_proto generic +_supported_os Linux + +echo +echo "== check that the first sector can be read ==" +_use_sample_img simple-pattern.cloop.bz2 +$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out new file mode 100644 index 0000000..26661fa --- /dev/null +++ b/tests/qemu-iotests/075.out @@ -0,0 +1,6 @@ +QA output created by 075 + +== check that the first sector can be read == +read 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index ee09ebc..633e82d 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -81,6 +81,7 @@ 072 rw auto quick 073 rw auto quick 074 rw auto quick +075 rw auto 077 rw auto quick 079 rw auto 081 rw auto diff --git a/tests/qemu-iotests/sample_images/simple-pattern.cloop.bz2 b/tests/qemu-iotests/sample_images/simple-pattern.cloop.bz2 new file mode 100644 index 0000000..a02d2ee Binary files /dev/null and b/tests/qemu-iotests/sample_images/simple-pattern.cloop.bz2 differ -- cgit v1.1 From d65f97a82c4ed48374a764c769d4ba1ea9724e97 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Mar 2014 13:05:25 +0100 Subject: block/cloop: validate block_size header field (CVE-2014-0144) Avoid unbounded s->uncompressed_block memory allocation by checking that the block_size header field has a reasonable value. Also enforce the assumption that the value is a non-zero multiple of 512. These constraints conform to cloop 2.639's code so we accept existing image files. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/075 | 20 ++++++++++++++++++++ tests/qemu-iotests/075.out | 12 ++++++++++++ 2 files changed, 32 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075 index 88ae8bb..8f54a99 100755 --- a/tests/qemu-iotests/075 +++ b/tests/qemu-iotests/075 @@ -42,11 +42,31 @@ _supported_fmt cloop _supported_proto generic _supported_os Linux +block_size_offset=128 + echo echo "== check that the first sector can be read ==" _use_sample_img simple-pattern.cloop.bz2 $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== block_size must be a multiple of 512 ==" +_use_sample_img simple-pattern.cloop.bz2 +poke_file "$TEST_IMG" "$block_size_offset" "\x00\x00\x02\x01" +$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir + +echo +echo "== block_size cannot be zero ==" +_use_sample_img simple-pattern.cloop.bz2 +poke_file "$TEST_IMG" "$block_size_offset" "\x00\x00\x00\x00" +$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir + +echo +echo "== huge block_size ===" +_use_sample_img simple-pattern.cloop.bz2 +poke_file "$TEST_IMG" "$block_size_offset" "\xff\xff\xfe\x00" +$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out index 26661fa..d362c95 100644 --- a/tests/qemu-iotests/075.out +++ b/tests/qemu-iotests/075.out @@ -3,4 +3,16 @@ QA output created by 075 == check that the first sector can be read == read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== block_size must be a multiple of 512 == +qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 513 must be a multiple of 512 +no file open, try 'help open' + +== block_size cannot be zero == +qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size cannot be zero +no file open, try 'help open' + +== huge block_size === +qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 4294966784 must be 64 MB or less +no file open, try 'help open' *** done -- cgit v1.1 From 509a41bab5306181044b5fff02eadf96d9c8676a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Mar 2014 13:05:26 +0100 Subject: block/cloop: prevent offsets_size integer overflow (CVE-2014-0143) The following integer overflow in offsets_size can lead to out-of-bounds memory stores when n_blocks has a huge value: uint32_t n_blocks, offsets_size; [...] ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4); [...] s->n_blocks = be32_to_cpu(s->n_blocks); /* read offsets */ offsets_size = s->n_blocks * sizeof(uint64_t); s->offsets = g_malloc(offsets_size); [...] for(i=0;in_blocks;i++) { s->offsets[i] = be64_to_cpu(s->offsets[i]); offsets_size can be smaller than n_blocks due to integer overflow. Therefore s->offsets[] is too small when the for loop byteswaps offsets. This patch refuses to open files if offsets_size would overflow. Note that changing the type of offsets_size is not a fix since 32-bit hosts still only have 32-bit size_t. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/075 | 7 +++++++ tests/qemu-iotests/075.out | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075 index 8f54a99..9ce6b1f 100755 --- a/tests/qemu-iotests/075 +++ b/tests/qemu-iotests/075 @@ -43,6 +43,7 @@ _supported_proto generic _supported_os Linux block_size_offset=128 +n_blocks_offset=132 echo echo "== check that the first sector can be read ==" @@ -67,6 +68,12 @@ _use_sample_img simple-pattern.cloop.bz2 poke_file "$TEST_IMG" "$block_size_offset" "\xff\xff\xfe\x00" $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== offsets_size overflow ===" +_use_sample_img simple-pattern.cloop.bz2 +poke_file "$TEST_IMG" "$n_blocks_offset" "\xff\xff\xff\xff" +$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out index d362c95..a771789 100644 --- a/tests/qemu-iotests/075.out +++ b/tests/qemu-iotests/075.out @@ -15,4 +15,8 @@ no file open, try 'help open' == huge block_size === qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 4294966784 must be 64 MB or less no file open, try 'help open' + +== offsets_size overflow === +qemu-io: can't open device TEST_DIR/simple-pattern.cloop: n_blocks 4294967295 must be 536870911 or less +no file open, try 'help open' *** done -- cgit v1.1 From 7b103b36d6ef3b11827c203d3a793bf7da50ecd6 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Mar 2014 13:05:27 +0100 Subject: block/cloop: refuse images with huge offsets arrays (CVE-2014-0144) Limit offsets_size to 512 MB so that: 1. g_malloc() does not abort due to an unreasonable size argument. 2. offsets_size does not overflow the bdrv_pread() int size argument. This limit imposes a maximum image size of 16 TB at 256 KB block size. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/075 | 6 ++++++ tests/qemu-iotests/075.out | 4 ++++ 2 files changed, 10 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075 index 9ce6b1f..9c00fa8 100755 --- a/tests/qemu-iotests/075 +++ b/tests/qemu-iotests/075 @@ -74,6 +74,12 @@ _use_sample_img simple-pattern.cloop.bz2 poke_file "$TEST_IMG" "$n_blocks_offset" "\xff\xff\xff\xff" $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== refuse images that require too many offsets ===" +_use_sample_img simple-pattern.cloop.bz2 +poke_file "$TEST_IMG" "$n_blocks_offset" "\x04\x00\x00\x01" +$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out index a771789..7cdaee1 100644 --- a/tests/qemu-iotests/075.out +++ b/tests/qemu-iotests/075.out @@ -19,4 +19,8 @@ no file open, try 'help open' == offsets_size overflow === qemu-io: can't open device TEST_DIR/simple-pattern.cloop: n_blocks 4294967295 must be 536870911 or less no file open, try 'help open' + +== refuse images that require too many offsets === +qemu-io: can't open device TEST_DIR/simple-pattern.cloop: image requires too many offsets, try increasing block size +no file open, try 'help open' *** done -- cgit v1.1 From f56b9bc3ae20fc93815b34aa022be919941406ce Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Mar 2014 13:05:28 +0100 Subject: block/cloop: refuse images with bogus offsets (CVE-2014-0144) The offsets[] array allows efficient seeking and tells us the maximum compressed data size. If the offsets are bogus the maximum compressed data size will be unrealistic. This could cause g_malloc() to abort and bogus offsets mean the image is broken anyway. Therefore we should refuse such images. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/075 | 15 +++++++++++++++ tests/qemu-iotests/075.out | 8 ++++++++ 2 files changed, 23 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075 index 9c00fa8..d74fb33 100755 --- a/tests/qemu-iotests/075 +++ b/tests/qemu-iotests/075 @@ -44,6 +44,7 @@ _supported_os Linux block_size_offset=128 n_blocks_offset=132 +offsets_offset=136 echo echo "== check that the first sector can be read ==" @@ -80,6 +81,20 @@ _use_sample_img simple-pattern.cloop.bz2 poke_file "$TEST_IMG" "$n_blocks_offset" "\x04\x00\x00\x01" $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== refuse images with non-monotonically increasing offsets ==" +_use_sample_img simple-pattern.cloop.bz2 +poke_file "$TEST_IMG" "$offsets_offset" "\x00\x00\x00\x00\xff\xff\xff\xff" +poke_file "$TEST_IMG" $((offsets_offset + 8)) "\x00\x00\x00\x00\xff\xfe\x00\x00" +$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir + +echo +echo "== refuse images with invalid compressed block size ==" +_use_sample_img simple-pattern.cloop.bz2 +poke_file "$TEST_IMG" "$offsets_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" +poke_file "$TEST_IMG" $((offsets_offset + 8)) "\xff\xff\xff\xff\xff\xff\xff\xff" +$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out index 7cdaee1..911cd3b 100644 --- a/tests/qemu-iotests/075.out +++ b/tests/qemu-iotests/075.out @@ -23,4 +23,12 @@ no file open, try 'help open' == refuse images that require too many offsets === qemu-io: can't open device TEST_DIR/simple-pattern.cloop: image requires too many offsets, try increasing block size no file open, try 'help open' + +== refuse images with non-monotonically increasing offsets == +qemu-io: can't open device TEST_DIR/simple-pattern.cloop: offsets not monotonically increasing at index 1, image file is corrupt +no file open, try 'help open' + +== refuse images with invalid compressed block size == +qemu-io: can't open device TEST_DIR/simple-pattern.cloop: invalid compressed block size at index 1, image file is corrupt +no file open, try 'help open' *** done -- cgit v1.1 From 42d43d35d907579179a39c924d169da924786f65 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 26 Mar 2014 13:05:29 +0100 Subject: block/cloop: fix offsets[] size off-by-one cloop stores the number of compressed blocks in the n_blocks header field. The file actually contains n_blocks + 1 offsets, where the extra offset is the end-of-file offset. The following line in cloop_read_block() results in an out-of-bounds offsets[] access: uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num]; This patch allocates and loads the extra offset so that cloop_read_block() works correctly when the last block is accessed. Notice that we must free s->offsets[] unconditionally now since there is always an end-of-file offset. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/075 | 5 +++++ tests/qemu-iotests/075.out | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075 index d74fb33..40032c5 100755 --- a/tests/qemu-iotests/075 +++ b/tests/qemu-iotests/075 @@ -52,6 +52,11 @@ _use_sample_img simple-pattern.cloop.bz2 $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir echo +echo "== check that the last sector can be read ==" +_use_sample_img simple-pattern.cloop.bz2 +$QEMU_IO -c "read $((1024 * 1024 - 512)) 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir + +echo echo "== block_size must be a multiple of 512 ==" _use_sample_img simple-pattern.cloop.bz2 poke_file "$TEST_IMG" "$block_size_offset" "\x00\x00\x02\x01" diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out index 911cd3b..5f1d6c1 100644 --- a/tests/qemu-iotests/075.out +++ b/tests/qemu-iotests/075.out @@ -4,6 +4,10 @@ QA output created by 075 read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +== check that the last sector can be read == +read 512/512 bytes at offset 1048064 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + == block_size must be a multiple of 512 == qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 513 must be a multiple of 512 no file open, try 'help open' -- cgit v1.1 From 24f3078a049c52070adfc659fc3a1a71a11a7765 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:30 +0100 Subject: qemu-iotests: Support for bochs format Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/078 | 53 +++++++++++++++++++++++ tests/qemu-iotests/078.out | 6 +++ tests/qemu-iotests/common | 7 +++ tests/qemu-iotests/group | 1 + tests/qemu-iotests/sample_images/empty.bochs.bz2 | Bin 0 -> 118 bytes 5 files changed, 67 insertions(+) create mode 100755 tests/qemu-iotests/078 create mode 100644 tests/qemu-iotests/078.out create mode 100644 tests/qemu-iotests/sample_images/empty.bochs.bz2 (limited to 'tests') diff --git a/tests/qemu-iotests/078 b/tests/qemu-iotests/078 new file mode 100755 index 0000000..f55f46d --- /dev/null +++ b/tests/qemu-iotests/078 @@ -0,0 +1,53 @@ +#!/bin/bash +# +# bochs format input validation tests +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt bochs +_supported_proto generic +_supported_os Linux + +echo +echo "== Read from a valid image ==" +_use_sample_img empty.bochs.bz2 +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out new file mode 100644 index 0000000..25d37c5 --- /dev/null +++ b/tests/qemu-iotests/078.out @@ -0,0 +1,6 @@ +QA output created by 078 + +== Read from a valid image == +read 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index 37e3bed..a09d9c8 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -136,6 +136,7 @@ common options check options -raw test raw (default) + -bochs test bochs -cow test cow -cloop test cloop -qcow test qcow @@ -174,6 +175,12 @@ testlist options xpand=false ;; + -bochs) + IMGFMT=bochs + IMGFMT_GENERIC=false + xpand=false + ;; + -cow) IMGFMT=cow xpand=false diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 633e82d..ecba432 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -83,6 +83,7 @@ 074 rw auto quick 075 rw auto 077 rw auto quick +078 rw auto 079 rw auto 081 rw auto 082 rw auto quick diff --git a/tests/qemu-iotests/sample_images/empty.bochs.bz2 b/tests/qemu-iotests/sample_images/empty.bochs.bz2 new file mode 100644 index 0000000..7a29c6e Binary files /dev/null and b/tests/qemu-iotests/sample_images/empty.bochs.bz2 differ -- cgit v1.1 From 246f65838d19db6db55bfb41117c35645a2c4789 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:32 +0100 Subject: bochs: Use unsigned variables for offsets and sizes (CVE-2014-0147) Gets us rid of integer overflows resulting in negative sizes which aren't correctly checked. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/078 | 8 ++++++++ tests/qemu-iotests/078.out | 4 ++++ 2 files changed, 12 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/078 b/tests/qemu-iotests/078 index f55f46d..73b573a 100755 --- a/tests/qemu-iotests/078 +++ b/tests/qemu-iotests/078 @@ -42,11 +42,19 @@ _supported_fmt bochs _supported_proto generic _supported_os Linux +catalog_size_offset=$((0x48)) + echo echo "== Read from a valid image ==" _use_sample_img empty.bochs.bz2 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Negative catalog size ==" +_use_sample_img empty.bochs.bz2 +poke_file "$TEST_IMG" "$catalog_size_offset" "\xff\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out index 25d37c5..ef8c42d 100644 --- a/tests/qemu-iotests/078.out +++ b/tests/qemu-iotests/078.out @@ -3,4 +3,8 @@ QA output created by 078 == Read from a valid image == read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== Negative catalog size == +qemu-io: can't open device TEST_DIR/empty.bochs: Could not open 'TEST_DIR/empty.bochs': Interrupted system call +no file open, try 'help open' *** done -- cgit v1.1 From e3737b820b45e54b059656dc3f914f895ac7a88b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:33 +0100 Subject: bochs: Check catalog_size header field (CVE-2014-0143) It should neither become negative nor allow unbounded memory allocations. This fixes aborts in g_malloc() and an s->catalog_bitmap buffer overflow on big endian hosts. Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/078 | 13 +++++++++++++ tests/qemu-iotests/078.out | 10 +++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/qemu-iotests/078 b/tests/qemu-iotests/078 index 73b573a..902ef0f 100755 --- a/tests/qemu-iotests/078 +++ b/tests/qemu-iotests/078 @@ -43,6 +43,7 @@ _supported_proto generic _supported_os Linux catalog_size_offset=$((0x48)) +disk_size_offset=$((0x58)) echo echo "== Read from a valid image ==" @@ -55,6 +56,18 @@ _use_sample_img empty.bochs.bz2 poke_file "$TEST_IMG" "$catalog_size_offset" "\xff\xff\xff\xff" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Overflow for catalog size * sizeof(uint32_t) ==" +_use_sample_img empty.bochs.bz2 +poke_file "$TEST_IMG" "$catalog_size_offset" "\x00\x00\x00\x40" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +echo +echo "== Too small catalog bitmap for image size ==" +_use_sample_img empty.bochs.bz2 +poke_file "$TEST_IMG" "$disk_size_offset" "\x00\xc0\x0f\x00\x00\x00\x00\x7f" +{ $QEMU_IO -c "read 2T 4k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out index ef8c42d..7254693 100644 --- a/tests/qemu-iotests/078.out +++ b/tests/qemu-iotests/078.out @@ -5,6 +5,14 @@ read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == Negative catalog size == -qemu-io: can't open device TEST_DIR/empty.bochs: Could not open 'TEST_DIR/empty.bochs': Interrupted system call +qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too large +no file open, try 'help open' + +== Overflow for catalog size * sizeof(uint32_t) == +qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too large +no file open, try 'help open' + +== Too small catalog bitmap for image size == +qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size no file open, try 'help open' *** done -- cgit v1.1 From 8e53abbc20d08ae3ec30c2054e1161314ad9501d Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:34 +0100 Subject: bochs: Check extent_size header field (CVE-2014-0142) This fixes two possible division by zero crashes: In bochs_open() and in seek_to_sector(). Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/078 | 13 +++++++++++++ tests/qemu-iotests/078.out | 8 ++++++++ 2 files changed, 21 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/078 b/tests/qemu-iotests/078 index 902ef0f..872e734 100755 --- a/tests/qemu-iotests/078 +++ b/tests/qemu-iotests/078 @@ -43,6 +43,7 @@ _supported_proto generic _supported_os Linux catalog_size_offset=$((0x48)) +extent_size_offset=$((0x50)) disk_size_offset=$((0x58)) echo @@ -68,6 +69,18 @@ _use_sample_img empty.bochs.bz2 poke_file "$TEST_IMG" "$disk_size_offset" "\x00\xc0\x0f\x00\x00\x00\x00\x7f" { $QEMU_IO -c "read 2T 4k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Negative extent size ==" +_use_sample_img empty.bochs.bz2 +poke_file "$TEST_IMG" "$extent_size_offset" "\xff\xff\xff\xff" +{ $QEMU_IO -c "read 768k 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +echo +echo "== Zero extent size ==" +_use_sample_img empty.bochs.bz2 +poke_file "$TEST_IMG" "$extent_size_offset" "\x00\x00\x00\x00" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out index 7254693..ea95ffd 100644 --- a/tests/qemu-iotests/078.out +++ b/tests/qemu-iotests/078.out @@ -15,4 +15,12 @@ no file open, try 'help open' == Too small catalog bitmap for image size == qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size no file open, try 'help open' + +== Negative extent size == +qemu-io: can't open device TEST_DIR/empty.bochs: Extent size 4294967295 is too large +no file open, try 'help open' + +== Zero extent size == +qemu-io: can't open device TEST_DIR/empty.bochs: Extent size may not be zero +no file open, try 'help open' *** done -- cgit v1.1 From 5e71dfad763d67bb64be79e20e93411c0c30ad25 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:37 +0100 Subject: vpc: Validate block size (CVE-2014-0142) This fixes some cases of division by zero crashes. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/088 | 64 ++++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/088.out | 17 ++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 82 insertions(+) create mode 100755 tests/qemu-iotests/088 create mode 100644 tests/qemu-iotests/088.out (limited to 'tests') diff --git a/tests/qemu-iotests/088 b/tests/qemu-iotests/088 new file mode 100755 index 0000000..c09adf8 --- /dev/null +++ b/tests/qemu-iotests/088 @@ -0,0 +1,64 @@ +#!/bin/bash +# +# vpc (VHD) format input validation tests +# +# Copyright (C) 2014 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + rm -f $TEST_IMG.snap + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt vpc +_supported_proto generic +_supported_os Linux + +offset_block_size=$((512 + 32)) + +echo +echo "== Invalid block size ==" +_make_test_img 64M +poke_file "$TEST_IMG" "$offset_block_size" "\x00\x00\x00\x00" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_block_size" "\x00\x00\x00\x80" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_block_size" "\x12\x34\x56\x78" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/088.out b/tests/qemu-iotests/088.out new file mode 100644 index 0000000..d961609 --- /dev/null +++ b/tests/qemu-iotests/088.out @@ -0,0 +1,17 @@ +QA output created by 088 + +== Invalid block size == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 0 +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 0 +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 128 +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 128 +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 305419896 +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 305419896 +no file open, try 'help open' +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index ecba432..9c99edc 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -91,3 +91,4 @@ 085 rw auto 086 rw auto quick 087 rw auto +088 rw auto -- cgit v1.1 From 24342f2cae47d03911e346fe1e520b00dc2818e0 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:41 +0100 Subject: qcow2: Check header_length (CVE-2014-0144) This fixes an unbounded allocation for s->unknown_header_fields. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/080 | 61 ++++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/080.out | 9 +++++++ tests/qemu-iotests/group | 1 + 3 files changed, 71 insertions(+) create mode 100755 tests/qemu-iotests/080 create mode 100644 tests/qemu-iotests/080.out (limited to 'tests') diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 new file mode 100755 index 0000000..6512701 --- /dev/null +++ b/tests/qemu-iotests/080 @@ -0,0 +1,61 @@ +#!/bin/bash +# +# qcow2 format input validation tests +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + +header_size=104 +offset_header_size=100 +offset_ext_magic=$header_size +offset_ext_size=$((header_size + 4)) + +echo +echo "== Huge header size ==" +_make_test_img 64M +poke_file "$TEST_IMG" "$offset_header_size" "\xff\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_header_size" "\x7f\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out new file mode 100644 index 0000000..41a166a --- /dev/null +++ b/tests/qemu-iotests/080.out @@ -0,0 +1,9 @@ +QA output created by 080 + +== Huge header size == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size +no file open, try 'help open' +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 9c99edc..ed44f35 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -85,6 +85,7 @@ 077 rw auto quick 078 rw auto 079 rw auto +080 rw auto 081 rw auto 082 rw auto quick 083 rw auto -- cgit v1.1 From a1b3955c9415b1e767c130a2f59fee6aa28e575b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:42 +0100 Subject: qcow2: Check backing_file_offset (CVE-2014-0144) Header, header extension and the backing file name must all be stored in the first cluster. Setting the backing file to a much higher value allowed header extensions to become much bigger than we want them to be (unbounded allocation). Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/080 | 12 ++++++++++++ tests/qemu-iotests/080.out | 7 +++++++ 2 files changed, 19 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 6512701..6d588dd 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -43,6 +43,8 @@ _supported_proto generic _supported_os Linux header_size=104 + +offset_backing_file_offset=8 offset_header_size=100 offset_ext_magic=$header_size offset_ext_size=$((header_size + 4)) @@ -55,6 +57,16 @@ poke_file "$TEST_IMG" "$offset_header_size" "\xff\xff\xff\xff" poke_file "$TEST_IMG" "$offset_header_size" "\x7f\xff\xff\xff" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Huge unknown header extension ==" +_make_test_img 64M +poke_file "$TEST_IMG" "$offset_backing_file_offset" "\xff\xff\xff\xff\xff\xff\xff\xff" +poke_file "$TEST_IMG" "$offset_ext_magic" "\x12\x34\x56\x78" +poke_file "$TEST_IMG" "$offset_ext_size" "\x7f\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 41a166a..48c40aa 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -6,4 +6,11 @@ qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size no file open, try 'help open' + +== Huge unknown header extension == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large +no file open, try 'help open' *** done -- cgit v1.1 From 5dab2faddc8eaa1fb1abdbe2f502001fc13a1b21 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:43 +0100 Subject: qcow2: Check refcount table size (CVE-2014-0144) Limit the in-memory reference count table size to 8 MB, it's enough in practice. This fixes an unbounded allocation as well as a buffer overflow in qcow2_refcount_init(). Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/080 | 10 ++++++++++ tests/qemu-iotests/080.out | 7 +++++++ 2 files changed, 17 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 6d588dd..6179e05 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -45,6 +45,7 @@ _supported_os Linux header_size=104 offset_backing_file_offset=8 +offset_refcount_table_clusters=56 offset_header_size=100 offset_ext_magic=$header_size offset_ext_size=$((header_size + 4)) @@ -67,6 +68,15 @@ poke_file "$TEST_IMG" "$offset_ext_size" "\x7f\xff\xff\xff" poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Huge refcount table size ==" +_make_test_img 64M +poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\xff\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\x00\x02\x00\x01" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 48c40aa..6fef6d9 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -13,4 +13,11 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large no file open, try 'help open' + +== Huge refcount table size == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large +no file open, try 'help open' *** done -- cgit v1.1 From 8c7de28305a514d7f879fdfc677ca11fbf60d2e9 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:44 +0100 Subject: qcow2: Validate refcount table offset The end of the refcount table must not exceed INT64_MAX so that integer overflows are avoided. Also check for misaligned refcount table. Such images are invalid and probably the result of data corruption. Error out to avoid further corruption. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/080 | 13 +++++++++++++ tests/qemu-iotests/080.out | 10 ++++++++++ 2 files changed, 23 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 6179e05..f58ac73 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -45,6 +45,7 @@ _supported_os Linux header_size=104 offset_backing_file_offset=8 +offset_refcount_table_offset=48 offset_refcount_table_clusters=56 offset_header_size=100 offset_ext_magic=$header_size @@ -76,6 +77,18 @@ poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\xff\xff\xff\xff" poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\x00\x02\x00\x01" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Misaligned refcount table ==" +_make_test_img 64M +poke_file "$TEST_IMG" "$offset_refcount_table_offset" "\x12\x34\x56\x78\x90\xab\xcd\xef" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +echo +echo "== Huge refcount offset ==" +_make_test_img 64M +poke_file "$TEST_IMG" "$offset_refcount_table_offset" "\xff\xff\xff\xff\xff\xff\x00\x00" +poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\x00\x00\x00\x7f" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir # success, all done echo "*** done" diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 6fef6d9..f919b58 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -20,4 +20,14 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large no file open, try 'help open' + +== Misaligned refcount table == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset +no file open, try 'help open' + +== Huge refcount offset == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset +no file open, try 'help open' *** done -- cgit v1.1 From ce48f2f441ca98885267af6fd636a7cb804ee646 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:45 +0100 Subject: qcow2: Validate snapshot table offset/size (CVE-2014-0144) This avoid unbounded memory allocation and fixes a potential buffer overflow on 32 bit hosts. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/080 | 27 +++++++++++++++++++++++++++ tests/qemu-iotests/080.out | 17 +++++++++++++++++ 2 files changed, 44 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index f58ac73..8a8b460 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -47,6 +47,8 @@ header_size=104 offset_backing_file_offset=8 offset_refcount_table_offset=48 offset_refcount_table_clusters=56 +offset_nb_snapshots=60 +offset_snapshots_offset=64 offset_header_size=100 offset_ext_magic=$header_size offset_ext_size=$((header_size + 4)) @@ -90,6 +92,31 @@ poke_file "$TEST_IMG" "$offset_refcount_table_offset" "\xff\xff\xff\xff\xff\xff\ poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\x00\x00\x00\x7f" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Invalid snapshot table ==" +_make_test_img 64M +poke_file "$TEST_IMG" "$offset_nb_snapshots" "\xff\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x7f\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +poke_file "$TEST_IMG" "$offset_snapshots_offset" "\xff\xff\xff\xff\xff\xff\x00\x00" +poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x00\x00\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +poke_file "$TEST_IMG" "$offset_snapshots_offset" "\x12\x34\x56\x78\x90\xab\xcd\xef" +poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x00\x00\x00\x00" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +echo +echo "== Hitting snapshot table size limit ==" +_make_test_img 64M +# Put the refcount table in a more or less safe place (16 MB) +poke_file "$TEST_IMG" "$offset_snapshots_offset" "\x00\x00\x00\x00\x01\x00\x00\x00" +poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x00\x01\x00\x00" +{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index f919b58..b06f47f 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -30,4 +30,21 @@ no file open, try 'help open' Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset no file open, try 'help open' + +== Invalid snapshot table == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open device TEST_DIR/t.qcow2: Too many snapshots +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Too many snapshots +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset +no file open, try 'help open' + +== Hitting snapshot table size limit == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: Could not create snapshot 'test': -27 (File too large) +read 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) *** done -- cgit v1.1 From 2d51c32c4b511db8bb9e58208f1e2c25e4c06c85 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:46 +0100 Subject: qcow2: Validate active L1 table offset and size (CVE-2014-0144) This avoids an unbounded allocation. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/080 | 18 ++++++++++++++++++ tests/qemu-iotests/080.out | 11 +++++++++++ 2 files changed, 29 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 8a8b460..7255b6c 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -45,6 +45,8 @@ _supported_os Linux header_size=104 offset_backing_file_offset=8 +offset_l1_size=36 +offset_l1_table_offset=40 offset_refcount_table_offset=48 offset_refcount_table_clusters=56 offset_nb_snapshots=60 @@ -117,6 +119,22 @@ poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x00\x01\x00\x00" { $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Invalid L1 table ==" +_make_test_img 64M +poke_file "$TEST_IMG" "$offset_l1_size" "\xff\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_l1_size" "\x7f\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +poke_file "$TEST_IMG" "$offset_l1_table_offset" "\x7f\xff\xff\xff\xff\xff\x00\x00" +poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +poke_file "$TEST_IMG" "$offset_l1_table_offset" "\x12\x34\x56\x78\x90\xab\xcd\xef" +poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index b06f47f..4ec2545 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -47,4 +47,15 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-img: Could not create snapshot 'test': -27 (File too large) read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== Invalid L1 table == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open device TEST_DIR/t.qcow2: Active L1 table too large +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Active L1 table too large +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset +no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset +no file open, try 'help open' *** done -- cgit v1.1 From 6d33e8e7dc9d40ea105feed4b39caa3e641569e8 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:05:47 +0100 Subject: qcow2: Fix backing file name length check len could become negative and would pass the check then. Nothing bad happened because bdrv_pread() happens to return an error for negative length values, but make variables for sizes unsigned anyway. This patch also changes the behaviour to error out on invalid lengths instead of silently truncating it to 1023. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/080 | 8 ++++++++ tests/qemu-iotests/080.out | 5 +++++ 2 files changed, 13 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 7255b6c..f3091a9 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -45,6 +45,7 @@ _supported_os Linux header_size=104 offset_backing_file_offset=8 +offset_backing_file_size=16 offset_l1_size=36 offset_l1_table_offset=40 offset_refcount_table_offset=48 @@ -135,6 +136,13 @@ poke_file "$TEST_IMG" "$offset_l1_table_offset" "\x12\x34\x56\x78\x90\xab\xcd\xe poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Invalid backing file size ==" +_make_test_img 64M +poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x10\x00" +poke_file "$TEST_IMG" "$offset_backing_file_size" "\xff\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 4ec2545..8103211 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -58,4 +58,9 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset no file open, try 'help open' + +== Invalid backing file size == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-io: can't open device TEST_DIR/t.qcow2: Backing file name too long +no file open, try 'help open' *** done -- cgit v1.1 From b106ad9185f35fc4ad669555ad0e79e276083bd7 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 28 Mar 2014 18:06:31 +0100 Subject: qcow2: Don't rely on free_cluster_index in alloc_refcount_block() (CVE-2014-0147) free_cluster_index is only correct if update_refcount() was called from an allocation function, and even there it's brittle because it's used to protect unfinished allocations which still have a refcount of 0 - if it moves in the wrong place, the unfinished allocation can be corrupted. So not using it any more seems to be a good idea. Instead, use the first requested cluster to do the calculations. Return -EAGAIN if unfinished allocations could become invalid and let the caller restart its search for some free clusters. The context of creating a snapsnot is one situation where update_refcount() is called outside of a cluster allocation. For this case, the change fixes a buffer overflow if a cluster is referenced in an L2 table that cannot be represented by an existing refcount block. (new_table[refcount_table_index] was out of bounds) [Bump the qemu-iotests 026 refblock_alloc.write leak count from 10 to 11. --Stefan] Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/026.out | 6 +++--- tests/qemu-iotests/044.out | 2 +- tests/qemu-iotests/080 | 11 +++++++++++ tests/qemu-iotests/080.out | 7 +++++++ 4 files changed, 22 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out index 1504579..f7c78e7 100644 --- a/tests/qemu-iotests/026.out +++ b/tests/qemu-iotests/026.out @@ -475,7 +475,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write write failed: No space left on device -10 leaked clusters were found on the image. +11 leaked clusters were found on the image. This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -499,7 +499,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write write failed: No space left on device -10 leaked clusters were found on the image. +11 leaked clusters were found on the image. This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -523,7 +523,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write write failed: No space left on device -10 leaked clusters were found on the image. +11 leaked clusters were found on the image. This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out index 5c5aa92..4789a53 100644 --- a/tests/qemu-iotests/044.out +++ b/tests/qemu-iotests/044.out @@ -1,6 +1,6 @@ No errors were found on the image. 7292415/33554432 = 21.73% allocated, 0.00% fragmented, 0.00% compressed clusters -Image end offset: 4296448000 +Image end offset: 4296152064 . ---------------------------------------------------------------------- Ran 1 tests diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index f3091a9..56f8903 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -56,6 +56,8 @@ offset_header_size=100 offset_ext_magic=$header_size offset_ext_size=$((header_size + 4)) +offset_l2_table_0=$((0x40000)) + echo echo "== Huge header size ==" _make_test_img 64M @@ -143,6 +145,15 @@ poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x1 poke_file "$TEST_IMG" "$offset_backing_file_size" "\xff\xff\xff\xff" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Invalid L2 entry (huge physical offset) ==" +_make_test_img 64M +{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_l2_table_0" "\xbf\xff\xff\xff\xff\xff\x00\x00" +{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_l2_table_0" "\x80\x00\x00\xff\xff\xff\x00\x00" +{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 8103211..303d6c3 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -63,4 +63,11 @@ no file open, try 'help open' Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Backing file name too long no file open, try 'help open' + +== Invalid L2 entry (huge physical offset) == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Could not create snapshot 'test': -27 (File too large) +qemu-img: Could not create snapshot 'test': -11 (Resource temporarily unavailable) *** done -- cgit v1.1 From 1e7226f70c9d944ae7f233b65fb4adda8f910dfe Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Fri, 28 Mar 2014 11:42:25 -0400 Subject: block: vdi bounds check qemu-io tests This test checks for proper bounds checking of some VDI input headers. The following is checked: 1. Max image size (1024TB) with the appropriate Blocks In Image value (0x3fffffff) is detected as valid. 2. Image size exceeding max (1024TB) is seen as invalid 3. Valid image size but with Blocks In Image value that is too small fails 4. Blocks In Image size exceeding max (0x3fffffff) is seen as invalid 5. 64MB image, with 64 Blocks In Image, and 1MB Block Size is seen as valid 6. Block Size < 1MB not supported 7. Block Size > 1MB not supported [Max Reitz pointed out that "1MB + 1" in the test case is wrong. Change to "1MB + 64KB" to match the 0x110000 value. --Stefan] Signed-off-by: Jeff Cody Reviewed-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/084 | 104 +++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/084.out | 33 ++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 138 insertions(+) create mode 100755 tests/qemu-iotests/084 create mode 100644 tests/qemu-iotests/084.out (limited to 'tests') diff --git a/tests/qemu-iotests/084 b/tests/qemu-iotests/084 new file mode 100755 index 0000000..cb4d7b7 --- /dev/null +++ b/tests/qemu-iotests/084 @@ -0,0 +1,104 @@ +#!/bin/bash +# +# Test case for VDI header corruption; image too large, and too many blocks +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=jcody@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# This tests vdi-specific header fields +_supported_fmt vdi +_supported_proto generic +_supported_os Linux + +ds_offset=368 # disk image size field offset +bs_offset=376 # block size field offset +bii_offset=384 # block in image field offset + +echo +echo "=== Testing image size bounds ===" +echo +_make_test_img 64M + +# check for image size too large +# poke max image size, and appropriate blocks_in_image value +echo "Test 1: Maximum size (1024 TB):" +poke_file "$TEST_IMG" "$ds_offset" "\x00\x00\xf0\xff\xff\xff\x03\x00" +poke_file "$TEST_IMG" "$bii_offset" "\xff\xff\xff\x3f" +_img_info + +echo +echo "Test 2: Size too large (1024TB + 1)" +# This should be too large (-EINVAL): +poke_file "$TEST_IMG" "$ds_offset" "\x00\x00\xf1\xff\xff\xff\x03\x00" +_img_info + +echo +echo "Test 3: Size valid (64M), but Blocks In Image too small (63)" +# This sets the size to 64M, but with a blocks_in_image size that is +# too small +poke_file "$TEST_IMG" "$ds_offset" "\x00\x00\x00\x04\x00\x00\x00\x00" +# For a 64M image, we would need a blocks_in_image value of at least 64, +# so 63 should be too small and give us -ENOTSUP +poke_file "$TEST_IMG" "$bii_offset" "\x3f\x00\x00\x00" +_img_info + +echo +echo "Test 4: Size valid (64M), but Blocks In Image exceeds max allowed" +# Now check the bounds of blocks_in_image - 0x3fffffff should be the max +# value here, and we should get -ENOTSUP +poke_file "$TEST_IMG" "$bii_offset" "\x00\x00\x00\x40" +_img_info + +# Finally, 1MB is the only block size supported. Verify that +# a value != 1MB results in error, both smaller and larger +echo +echo "Test 5: Valid Image: 64MB, Blocks In Image 64, Block Size 1MB" +poke_file "$TEST_IMG" "$bii_offset" "\x40\x00\x00\x00" # reset bii to valid +poke_file "$TEST_IMG" "$bs_offset" "\x00\x00\x10\x00" # valid +_img_info +echo +echo "Test 6: Block Size != 1MB; too small test (1MB - 1)" +poke_file "$TEST_IMG" "$bs_offset" "\xff\xff\x0f\x00" # invalid (too small) +_img_info +echo +echo "Test 7: Block Size != 1MB; too large test (1MB + 64KB)" +poke_file "$TEST_IMG" "$bs_offset" "\x00\x00\x11\x00" # invalid (too large) +_img_info +# success, all done +echo +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/084.out b/tests/qemu-iotests/084.out new file mode 100644 index 0000000..e681924 --- /dev/null +++ b/tests/qemu-iotests/084.out @@ -0,0 +1,33 @@ +QA output created by 084 + +=== Testing image size bounds === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Test 1: Maximum size (1024 TB): +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 1024T (1125899905794048 bytes) +cluster_size: 1048576 + +Test 2: Size too large (1024TB + 1) +qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported VDI image size (size is 0x3fffffff10000, max supported is 0x3fffffff00000) + +Test 3: Size valid (64M), but Blocks In Image too small (63) +qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (disk size 67108864, image bitmap has room for 66060288) + +Test 4: Size valid (64M), but Blocks In Image exceeds max allowed +qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (too many blocks 1073741824, max is 1073741823) + +Test 5: Valid Image: 64MB, Blocks In Image 64, Block Size 1MB +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 64M (67108864 bytes) +cluster_size: 1048576 + +Test 6: Block Size != 1MB; too small test (1MB - 1) +qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (block size 1048575 is not 1048576) + +Test 7: Block Size != 1MB; too large test (1MB + 64KB) +qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (block size 1114112 is not 1048576) + +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index ed44f35..c51640c 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -89,6 +89,7 @@ 081 rw auto 082 rw auto quick 083 rw auto +084 img auto 085 rw auto 086 rw auto quick 087 rw auto -- cgit v1.1 From 6b7d4c55586a849aa8313282d79432917eade3bf Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:06:03 +0100 Subject: qcow2: Fix copy_sectors() with VM state bs->total_sectors is not the highest possible sector number that could be involved in a copy on write operation: VM state is after the end of the virtual disk. This resulted in wrong values for the number of sectors to be copied (n). The code that checks for the end of the image isn't required any more because the code hasn't been calling the block layer's bdrv_read() for a long time; instead, it directly calls qcow2_readv(), which doesn't error out on VM state sector numbers. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/029 | 22 ++++++++++++++++++++-- tests/qemu-iotests/029.out | 13 +++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029 index b424726..567e071 100755 --- a/tests/qemu-iotests/029 +++ b/tests/qemu-iotests/029 @@ -1,7 +1,6 @@ #!/bin/bash # -# Test loading internal snapshots where the L1 table of the snapshot -# is smaller than the current L1 table. +# qcow2 internal snapshots/VM state tests # # Copyright (C) 2011 Red Hat, Inc. # @@ -45,6 +44,11 @@ _supported_fmt qcow2 _supported_proto generic _supported_os Linux +echo +echo Test loading internal snapshots where the L1 table of the snapshot +echo is smaller than the current L1 table. +echo + CLUSTER_SIZE=65536 _make_test_img 64M $QEMU_IMG snapshot -c foo "$TEST_IMG" @@ -59,6 +63,20 @@ $QEMU_IO -c 'write -b 0 4M' "$TEST_IMG" | _filter_qemu_io $QEMU_IMG snapshot -a foo "$TEST_IMG" _check_test_img + +echo +echo Try using a huge VM state +echo + +CLUSTER_SIZE=65536 +_make_test_img 64M +{ $QEMU_IO -c "write -b -P 0x11 1T 4k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +{ $QEMU_IMG snapshot -c foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +{ $QEMU_IMG snapshot -a foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +{ $QEMU_IO -c "read -b -P 0x11 1T 4k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +_check_test_img + + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/029.out b/tests/qemu-iotests/029.out index 0eedb3a..9029698 100644 --- a/tests/qemu-iotests/029.out +++ b/tests/qemu-iotests/029.out @@ -1,4 +1,8 @@ QA output created by 029 + +Test loading internal snapshots where the L1 table of the snapshot +is smaller than the current L1 table. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -7,4 +11,13 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 wrote 4194304/4194304 bytes at offset 0 4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) No errors were found on the image. + +Try using a huge VM state + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +wrote 4096/4096 bytes at offset 1099511627776 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +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. *** done -- cgit v1.1 From 11b128f4062dd7f89b14abc8877ff20d41b28be9 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:06:04 +0100 Subject: qcow2: Fix NULL dereference in qcow2_open() error path (CVE-2014-0146) The qcow2 code assumes that s->snapshots is non-NULL if s->nb_snapshots != 0. By having the initialisation of both fields separated in qcow2_open(), any error occuring in between would cause the error path to dereference NULL in qcow2_free_snapshots() if the image had any snapshots. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/080 | 7 +++++++ tests/qemu-iotests/080.out | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 56f8903..59e7a44 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -139,6 +139,13 @@ poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir echo +echo "== Invalid L1 table (with internal snapshot in the image) ==" +_make_test_img 64M +{ $QEMU_IMG snapshot -c foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x00" +_img_info + +echo echo "== Invalid backing file size ==" _make_test_img 64M poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x10\x00" diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 303d6c3..4d84fbf 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -59,6 +59,10 @@ no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset no file open, try 'help open' +== Invalid L1 table (with internal snapshot in the image) == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: Could not open 'TEST_DIR/t.IMGFMT': L1 table is too small + == Invalid backing file size == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: can't open device TEST_DIR/t.qcow2: Backing file name too long -- cgit v1.1 From c05e4667be91b46ab42b5a11babf8e84d476cc6b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:06:05 +0100 Subject: qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp() (CVE-2014-0145) 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 Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/029 | 18 +++++++++++++++++- tests/qemu-iotests/029.out | 4 ++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029 index 567e071..fa46ace 100755 --- a/tests/qemu-iotests/029 +++ b/tests/qemu-iotests/029 @@ -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 diff --git a/tests/qemu-iotests/029.out b/tests/qemu-iotests/029.out index 9029698..ce0e64d 100644 --- a/tests/qemu-iotests/029.out +++ b/tests/qemu-iotests/029.out @@ -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 -- cgit v1.1 From 6a83f8b5bec6f59e56cc49bd49e4c3f8f805d56f Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:06:06 +0100 Subject: qcow2: Check maximum L1 size in qcow2_snapshot_load_tmp() (CVE-2014-0143) This avoids an unbounded allocation. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/080 | 15 ++++++++++++++- tests/qemu-iotests/080.out | 6 ++++++ 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 index 59e7a44..6b3a3e7 100755 --- a/tests/qemu-iotests/080 +++ b/tests/qemu-iotests/080 @@ -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 @@ -58,6 +59,10 @@ offset_ext_size=$((header_size + 4)) offset_l2_table_0=$((0x40000)) +offset_snap1=$((0x70000)) +offset_snap1_l1_offset=$((offset_snap1 + 0)) +offset_snap1_l1_size=$((offset_snap1 + 8)) + echo echo "== Huge header size ==" _make_test_img 64M @@ -161,6 +166,14 @@ poke_file "$TEST_IMG" "$offset_l2_table_0" "\xbf\xff\xff\xff\xff\xff\x00\x00" poke_file "$TEST_IMG" "$offset_l2_table_0" "\x80\x00\x00\xff\xff\xff\x00\x00" { $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Invalid snapshot L1 table ==" +_make_test_img 64M +{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir +poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00" +{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index 4d84fbf..f7a943c 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -74,4 +74,10 @@ wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) qemu-img: Could not create snapshot 'test': -27 (File too large) qemu-img: Could not create snapshot 'test': -11 (Resource temporarily unavailable) + +== Invalid snapshot L1 table == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Failed to load snapshot: Snapshot L1 table too large *** done -- cgit v1.1 From afbcc40bee4ef51731102d7d4b499ee12fc182e1 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:06:08 +0100 Subject: parallels: Fix catalog size integer overflow (CVE-2014-0143) The first test case would cause a huge memory allocation, leading to a qemu abort; the second one to a too small malloc() for the catalog (smaller than s->catalog_size), which causes a read-only out-of-bounds array access and on big endian hosts an endianess conversion for an undefined memory area. The sample image used here is not an original Parallels image. It was created using an hexeditor on the basis of the struct that qemu uses. Good enough for trying to crash the driver, but not for ensuring compatibility. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/076 | 69 +++++++++++++++++++++ tests/qemu-iotests/076.out | 14 +++++ tests/qemu-iotests/common | 7 +++ tests/qemu-iotests/group | 1 + .../qemu-iotests/sample_images/fake.parallels.bz2 | Bin 0 -> 141 bytes 5 files changed, 91 insertions(+) create mode 100755 tests/qemu-iotests/076 create mode 100644 tests/qemu-iotests/076.out create mode 100644 tests/qemu-iotests/sample_images/fake.parallels.bz2 (limited to 'tests') diff --git a/tests/qemu-iotests/076 b/tests/qemu-iotests/076 new file mode 100755 index 0000000..6028ac5 --- /dev/null +++ b/tests/qemu-iotests/076 @@ -0,0 +1,69 @@ +#!/bin/bash +# +# parallels format input validation tests +# +# Copyright (C) 2013 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt parallels +_supported_proto generic +_supported_os Linux + +catalog_entries_offset=$((0x20)) +nb_sectors_offset=$((0x24)) + +echo +echo "== Read from a valid (enough) image ==" +_use_sample_img fake.parallels.bz2 +{ $QEMU_IO -c "read -P 0x11 0 64k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +echo +echo "== Negative catalog size ==" +_use_sample_img fake.parallels.bz2 +poke_file "$TEST_IMG" "$catalog_entries_offset" "\xff\xff\xff\xff" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +echo +echo "== Overflow in catalog allocation ==" +_use_sample_img fake.parallels.bz2 +poke_file "$TEST_IMG" "$nb_sectors_offset" "\xff\xff\xff\xff" +poke_file "$TEST_IMG" "$catalog_entries_offset" "\x01\x00\x00\x40" +{ $QEMU_IO -c "read 64M 64M" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/076.out b/tests/qemu-iotests/076.out new file mode 100644 index 0000000..12af42a --- /dev/null +++ b/tests/qemu-iotests/076.out @@ -0,0 +1,14 @@ +QA output created by 076 + +== Read from a valid (enough) image == +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== Negative catalog size == +qemu-io: can't open device TEST_DIR/fake.parallels: Catalog too large +no file open, try 'help open' + +== Overflow in catalog allocation == +qemu-io: can't open device TEST_DIR/fake.parallels: Catalog too large +no file open, try 'help open' +*** done diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index a09d9c8..0aaf84d 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -139,6 +139,7 @@ check options -bochs test bochs -cow test cow -cloop test cloop + -parallels test parallels -qcow test qcow -qcow2 test qcow2 -qed test qed @@ -192,6 +193,12 @@ testlist options xpand=false ;; + -parallels) + IMGFMT=parallels + IMGFMT_GENERIC=false + xpand=false + ;; + -qcow) IMGFMT=qcow xpand=false diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index c51640c..864643d 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -82,6 +82,7 @@ 073 rw auto quick 074 rw auto quick 075 rw auto +076 auto 077 rw auto quick 078 rw auto 079 rw auto diff --git a/tests/qemu-iotests/sample_images/fake.parallels.bz2 b/tests/qemu-iotests/sample_images/fake.parallels.bz2 new file mode 100644 index 0000000..ffb5f13 Binary files /dev/null and b/tests/qemu-iotests/sample_images/fake.parallels.bz2 differ -- cgit v1.1 From 9302e863aa8baa5d932fc078967050c055fa1a7f Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 26 Mar 2014 13:06:09 +0100 Subject: parallels: Sanity check for s->tracks (CVE-2014-0142) This avoids a possible division by zero. Convert s->tracks to unsigned as well because it feels better than surviving just because the results of calculations with s->tracks are converted to unsigned anyway. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz Signed-off-by: Stefan Hajnoczi --- tests/qemu-iotests/076 | 7 +++++++ tests/qemu-iotests/076.out | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'tests') diff --git a/tests/qemu-iotests/076 b/tests/qemu-iotests/076 index 6028ac5..b614a7d 100755 --- a/tests/qemu-iotests/076 +++ b/tests/qemu-iotests/076 @@ -42,6 +42,7 @@ _supported_fmt parallels _supported_proto generic _supported_os Linux +tracks_offset=$((0x1c)) catalog_entries_offset=$((0x20)) nb_sectors_offset=$((0x24)) @@ -63,6 +64,12 @@ poke_file "$TEST_IMG" "$nb_sectors_offset" "\xff\xff\xff\xff" poke_file "$TEST_IMG" "$catalog_entries_offset" "\x01\x00\x00\x40" { $QEMU_IO -c "read 64M 64M" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir +echo +echo "== Zero sectors per track ==" +_use_sample_img fake.parallels.bz2 +poke_file "$TEST_IMG" "$tracks_offset" "\x00\x00\x00\x00" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/076.out b/tests/qemu-iotests/076.out index 12af42a..f7745d8 100644 --- a/tests/qemu-iotests/076.out +++ b/tests/qemu-iotests/076.out @@ -11,4 +11,8 @@ no file open, try 'help open' == Overflow in catalog allocation == qemu-io: can't open device TEST_DIR/fake.parallels: Catalog too large no file open, try 'help open' + +== Zero sectors per track == +qemu-io: can't open device TEST_DIR/fake.parallels: Invalid image: Zero sectors per track +no file open, try 'help open' *** done -- cgit v1.1