Commit 93bbaf03 authored by Max Reitz's avatar Max Reitz
Browse files

qcow2: Unaligned zero cluster in handle_alloc()



We should check whether the cluster offset we are about to use is
actually valid; that is, whether it is aligned to cluster boundaries.

Reported-by: default avatarR. Nageswara Sastry <nasastry@in.ibm.com>
Buglink: https://bugs.launchpad.net/qemu/+bug/1728643
Buglink: https://bugs.launchpad.net/qemu/+bug/1728657


Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
Message-id: 20171110203111.7666-3-mreitz@redhat.com
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
Reviewed-by: default avatarAlberto Garcia <berto@igalia.com>
Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
parent 791fff50
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -1308,10 +1308,21 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
        (!*host_offset ||
         start_of_cluster(s, *host_offset) == (entry & L2E_OFFSET_MASK)))
    {
        int preallocated_nb_clusters;

        if (offset_into_cluster(s, entry & L2E_OFFSET_MASK)) {
            qcow2_signal_corruption(bs, true, -1, -1, "Preallocated zero "
                                    "cluster offset %#llx unaligned (guest "
                                    "offset: %#" PRIx64 ")",
                                    entry & L2E_OFFSET_MASK, guest_offset);
            ret = -EIO;
            goto fail;
        }

        /* Try to reuse preallocated zero clusters; contiguous normal clusters
         * would be fine, too, but count_cow_clusters() above has limited
         * nb_clusters already to a range of COW clusters */
        int preallocated_nb_clusters =
        preallocated_nb_clusters =
            count_contiguous_clusters(nb_clusters, s->cluster_size,
                                      &l2_table[l2_index], QCOW_OFLAG_COPIED);
        assert(preallocated_nb_clusters > 0);
+16 −0
Original line number Diff line number Diff line
@@ -321,6 +321,22 @@ echo '--- Repairing ---'
# because the image was already marked corrupt by that point
_check_test_img -r all

echo
echo "=== Writing to an unaligned preallocated zero cluster ==="
echo

_make_test_img 64M

# Allocate the L2 table
$QEMU_IO -c "write 0 64k" -c "discard 0 64k" "$TEST_IMG" | _filter_qemu_io
# Pretend there is a preallocated zero cluster somewhere inside the
# image header
poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x00\x2a\x01"
# Let's write to it!
$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io

# Can't repair this yet (TODO: We can just deallocate the cluster)

# success, all done
echo "*** done"
rm -f $seq.full
+10 −0
Original line number Diff line number Diff line
@@ -307,4 +307,14 @@ The following inconsistencies were found and repaired:

Double checking the fixed image now...
No errors were found on the image.

=== Writing to an unaligned preallocated zero cluster ===

Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
discard 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: Preallocated zero cluster offset 0x2a00 unaligned (guest offset: 0); further corruption events will be suppressed
write failed: Input/output error
*** done