9ae3a8
From cd10207e755b1b0470503c72c78a8d927f87a37a Mon Sep 17 00:00:00 2001
9ae3a8
From: Max Reitz <mreitz@redhat.com>
9ae3a8
Date: Sat, 13 Jun 2015 16:21:58 +0200
9ae3a8
Subject: [PATCH 04/42] qcow2: Catch !*host_offset for data allocation
9ae3a8
9ae3a8
Message-id: <1434212556-3927-5-git-send-email-mreitz@redhat.com>
9ae3a8
Patchwork-id: 66023
9ae3a8
O-Subject: [RHEL-7.2 qemu-kvm PATCH 04/42] qcow2: Catch !*host_offset for data allocation
9ae3a8
Bugzilla: 1129893
9ae3a8
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
9ae3a8
RH-Acked-by: Fam Zheng <famz@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
9ae3a8
BZ: 1129893
9ae3a8
9ae3a8
qcow2_alloc_cluster_offset() uses host_offset == 0 as "no preferred
9ae3a8
offset" for the (data) cluster range to be allocated. However, this
9ae3a8
offset is actually valid and may be allocated on images with a corrupted
9ae3a8
refcount table or first refcount block.
9ae3a8
9ae3a8
In this case, the corruption prevention should normally catch that
9ae3a8
write anyway (because it would overwrite the image header). But since 0
9ae3a8
is a special value here, the function assumes that nothing has been
9ae3a8
allocated at all which it asserts against.
9ae3a8
9ae3a8
Because this condition is not qemu's fault but rather that of a broken
9ae3a8
image, it shouldn't throw an assertion but rather mark the image corrupt
9ae3a8
and show an appropriate message, which this patch does by calling the
9ae3a8
corruption check earlier than it would be called normally (before the
9ae3a8
assertion).
9ae3a8
9ae3a8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9ae3a8
Reviewed-by: Eric Blake <eblake@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit ff52aab2df5c5e10f231481961b88d25a3021724)
9ae3a8
9ae3a8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 block/qcow2-cluster.c | 11 +++++++++++
9ae3a8
 1 file changed, 11 insertions(+)
9ae3a8
9ae3a8
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
9ae3a8
index 1b9609f..f2f1170 100644
9ae3a8
--- a/block/qcow2-cluster.c
9ae3a8
+++ b/block/qcow2-cluster.c
9ae3a8
@@ -1089,6 +1089,17 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
9ae3a8
         return 0;
9ae3a8
     }
9ae3a8
 
9ae3a8
+    /* !*host_offset would overwrite the image header and is reserved for "no
9ae3a8
+     * host offset preferred". If 0 was a valid host offset, it'd trigger the
9ae3a8
+     * following overlap check; do that now to avoid having an invalid value in
9ae3a8
+     * *host_offset. */
9ae3a8
+    if (!alloc_cluster_offset) {
9ae3a8
+        ret = qcow2_pre_write_overlap_check(bs, 0, alloc_cluster_offset,
9ae3a8
+                                            nb_clusters * s->cluster_size);
9ae3a8
+        assert(ret < 0);
9ae3a8
+        goto fail;
9ae3a8
+    }
9ae3a8
+
9ae3a8
     /*
9ae3a8
      * Save info needed for meta data update.
9ae3a8
      *
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8