9ae3a8
From 6fb76589c86264784014d8b555dc9c479c534898 Mon Sep 17 00:00:00 2001
9ae3a8
From: Jeffrey Cody <jcody@redhat.com>
9ae3a8
Date: Tue, 27 May 2014 19:05:11 +0200
9ae3a8
Subject: [PATCH 07/13] block: vhdx - account for identical header sections
9ae3a8
MIME-Version: 1.0
9ae3a8
Content-Type: text/plain; charset=UTF-8
9ae3a8
Content-Transfer-Encoding: 8bit
9ae3a8
9ae3a8
RH-Author: Jeffrey Cody <jcody@redhat.com>
9ae3a8
Message-id: <6a956eaa23796489845aaf8b0ef8aa390014e98b.1401217451.git.jcody@redhat.com>
9ae3a8
Patchwork-id: 59040
9ae3a8
O-Subject: [PATCH qemu-kvm RHEL7.1] block: vhdx - account for identical header sections
9ae3a8
Bugzilla: 1097020
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
RH-Acked-by: Fam Zheng <famz@redhat.com>
9ae3a8
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
9ae3a8
The VHDX spec v1.00 declares that "a header is current if it is the only
9ae3a8
valid header or if it is valid and its SequenceNumber field is greater
9ae3a8
than the other header’s SequenceNumber field. The parser must only use
9ae3a8
data from the current header. If there is no current header, then the
9ae3a8
VHDX file is corrupt."
9ae3a8
9ae3a8
However, the Disk2VHD tool from Microsoft creates a VHDX image file that
9ae3a8
has 2 identical headers, including matching checksums and matching
9ae3a8
sequence numbers.  Likely, as a shortcut the tool is just writing the
9ae3a8
header twice, for the active and inactive headers, during the image
9ae3a8
creation.  Technically, this should be considered a corrupt VHDX file
9ae3a8
(at least per the 1.00 spec, and that is how we currently treat it).
9ae3a8
9ae3a8
But in order to accomodate images created with Disk2VHD, we can safely
9ae3a8
create an exception for this case.  If we find identical sequence
9ae3a8
numbers, then we check the VHDXHeader-sized chunks of each 64KB header
9ae3a8
sections (we won't rely just on the crc32c to indicate the headers are
9ae3a8
the same).  If they are identical, then we go ahead and use the first
9ae3a8
one.
9ae3a8
9ae3a8
Reported-by: Nerijus Baliūnas <nerijus@users.sourceforge.net>
9ae3a8
Signed-off-by: Jeff Cody <jcody@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit 6906046169ffa9d829beeeaafe1fadeba51669fb)
9ae3a8
9ae3a8
Conflicts:
9ae3a8
	block/vhdx.c
9ae3a8
9ae3a8
Signed-off-by: Jeff Cody <jcody@redhat.com>
9ae3a8
---
9ae3a8
Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=7505809
9ae3a8
BZ: 1097020
9ae3a8
9ae3a8
Conflict notes: the conflict was with the ret value; current upstream
9ae3a8
                removed that in favor of passing in errp to the function
9ae3a8
9ae3a8
 block/vhdx.c | 11 +++++++++--
9ae3a8
 1 file changed, 9 insertions(+), 2 deletions(-)
9ae3a8
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 block/vhdx.c |   11 +++++++++--
9ae3a8
 1 files changed, 9 insertions(+), 2 deletions(-)
9ae3a8
9ae3a8
diff --git a/block/vhdx.c b/block/vhdx.c
9ae3a8
index 66a25c9..21ad6ad 100644
9ae3a8
--- a/block/vhdx.c
9ae3a8
+++ b/block/vhdx.c
9ae3a8
@@ -473,8 +473,15 @@ static int vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s)
9ae3a8
         } else if (h2_seq > h1_seq) {
9ae3a8
             s->curr_header = 1;
9ae3a8
         } else {
9ae3a8
-            ret = -EINVAL;
9ae3a8
-            goto fail;
9ae3a8
+            /* The Microsoft Disk2VHD tool will create 2 identical
9ae3a8
+             * headers, with identical sequence numbers.  If the headers are
9ae3a8
+             * identical, don't consider the file corrupt */
9ae3a8
+            if (!memcmp(header1, header2, sizeof(VHDXHeader))) {
9ae3a8
+                s->curr_header = 0;
9ae3a8
+            } else {
9ae3a8
+                ret = -EINVAL;
9ae3a8
+                goto fail;
9ae3a8
+            }
9ae3a8
         }
9ae3a8
     }
9ae3a8
 
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8