|
|
9bac43 |
From 97c8bc6029a1f88ee5bd737b2bf257139d533fea Mon Sep 17 00:00:00 2001
|
|
|
9bac43 |
From: "Daniel P. Berrange" <berrange@redhat.com>
|
|
|
9bac43 |
Date: Wed, 29 Nov 2017 15:09:20 +0100
|
|
|
9bac43 |
Subject: [PATCH 02/36] qcow2: fix image corruption after committing qcow2
|
|
|
9bac43 |
image into base
|
|
|
9bac43 |
|
|
|
9bac43 |
RH-Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
9bac43 |
Message-id: <20171129150920.8539-3-berrange@redhat.com>
|
|
|
9bac43 |
Patchwork-id: 77975
|
|
|
9bac43 |
O-Subject: [RHV-7.5 qemu-kvm-rhev PATCH 2/2] qcow2: fix image corruption after committing qcow2 image into base
|
|
|
9bac43 |
Bugzilla: 1406803
|
|
|
9bac43 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
9bac43 |
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
|
|
|
9bac43 |
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9bac43 |
|
|
|
9bac43 |
After committing the qcow2 image contents into the base image, qemu-img
|
|
|
9bac43 |
will call bdrv_make_empty to drop the payload in the layered image.
|
|
|
9bac43 |
|
|
|
9bac43 |
When this is done for qcow2 images, it blows away the LUKS encryption
|
|
|
9bac43 |
header, making the resulting image unusable. There are two codepaths
|
|
|
9bac43 |
for emptying a qcow2 image, and the second (slower) codepath leaves
|
|
|
9bac43 |
the LUKS header intact, so force use of that codepath.
|
|
|
9bac43 |
|
|
|
9bac43 |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
9bac43 |
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
|
|
|
9bac43 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9bac43 |
(cherry picked from commit f06033295b51d4868c2b4921ad2287e8f55eb688)
|
|
|
9bac43 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9bac43 |
|
|
|
9bac43 |
Conflicts:
|
|
|
9bac43 |
tests/qemu-iotests/group - some earlier tests don't exist yet
|
|
|
9bac43 |
---
|
|
|
9bac43 |
block/qcow2.c | 6 +-
|
|
|
9bac43 |
tests/qemu-iotests/198 | 104 ++++++++++++++++++++++++++++++++
|
|
|
9bac43 |
tests/qemu-iotests/198.out | 126 +++++++++++++++++++++++++++++++++++++++
|
|
|
9bac43 |
tests/qemu-iotests/common.filter | 4 +-
|
|
|
9bac43 |
tests/qemu-iotests/group | 1 +
|
|
|
9bac43 |
5 files changed, 238 insertions(+), 3 deletions(-)
|
|
|
9bac43 |
create mode 100755 tests/qemu-iotests/198
|
|
|
9bac43 |
create mode 100644 tests/qemu-iotests/198.out
|
|
|
9bac43 |
|
|
|
9bac43 |
diff --git a/block/qcow2.c b/block/qcow2.c
|
|
|
9bac43 |
index 6e8f753..a51efcc 100644
|
|
|
9bac43 |
--- a/block/qcow2.c
|
|
|
9bac43 |
+++ b/block/qcow2.c
|
|
|
9bac43 |
@@ -3567,12 +3567,14 @@ static int qcow2_make_empty(BlockDriverState *bs)
|
|
|
9bac43 |
l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / sizeof(uint64_t));
|
|
|
9bac43 |
|
|
|
9bac43 |
if (s->qcow_version >= 3 && !s->snapshots &&
|
|
|
9bac43 |
- 3 + l1_clusters <= s->refcount_block_size) {
|
|
|
9bac43 |
+ 3 + l1_clusters <= s->refcount_block_size &&
|
|
|
9bac43 |
+ s->crypt_method_header != QCOW_CRYPT_LUKS) {
|
|
|
9bac43 |
/* The following function only works for qcow2 v3 images (it requires
|
|
|
9bac43 |
* the dirty flag) and only as long as there are no snapshots (because
|
|
|
9bac43 |
* it completely empties the image). Furthermore, the L1 table and three
|
|
|
9bac43 |
* additional clusters (image header, refcount table, one refcount
|
|
|
9bac43 |
- * block) have to fit inside one refcount block. */
|
|
|
9bac43 |
+ * block) have to fit inside one refcount block. It cannot be used
|
|
|
9bac43 |
+ * for LUKS (yet) as it throws away the LUKS header cluster(s) */
|
|
|
9bac43 |
return make_completely_empty(bs);
|
|
|
9bac43 |
}
|
|
|
9bac43 |
|
|
|
9bac43 |
diff --git a/tests/qemu-iotests/198 b/tests/qemu-iotests/198
|
|
|
9bac43 |
new file mode 100755
|
|
|
9bac43 |
index 0000000..34ef666
|
|
|
9bac43 |
--- /dev/null
|
|
|
9bac43 |
+++ b/tests/qemu-iotests/198
|
|
|
9bac43 |
@@ -0,0 +1,104 @@
|
|
|
9bac43 |
+#!/bin/bash
|
|
|
9bac43 |
+#
|
|
|
9bac43 |
+# Test commit of encrypted qcow2 files
|
|
|
9bac43 |
+#
|
|
|
9bac43 |
+# Copyright (C) 2017 Red Hat, Inc.
|
|
|
9bac43 |
+#
|
|
|
9bac43 |
+# This program is free software; you can redistribute it and/or modify
|
|
|
9bac43 |
+# it under the terms of the GNU General Public License as published by
|
|
|
9bac43 |
+# the Free Software Foundation; either version 2 of the License, or
|
|
|
9bac43 |
+# (at your option) any later version.
|
|
|
9bac43 |
+#
|
|
|
9bac43 |
+# This program is distributed in the hope that it will be useful,
|
|
|
9bac43 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
9bac43 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
9bac43 |
+# GNU General Public License for more details.
|
|
|
9bac43 |
+#
|
|
|
9bac43 |
+# You should have received a copy of the GNU General Public License
|
|
|
9bac43 |
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
9bac43 |
+#
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+# creator
|
|
|
9bac43 |
+owner=berrange@redhat.com
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+seq=`basename $0`
|
|
|
9bac43 |
+echo "QA output created by $seq"
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+here=`pwd`
|
|
|
9bac43 |
+status=1 # failure is the default!
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+_cleanup()
|
|
|
9bac43 |
+{
|
|
|
9bac43 |
+ _cleanup_test_img
|
|
|
9bac43 |
+}
|
|
|
9bac43 |
+trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+# get standard environment, filters and checks
|
|
|
9bac43 |
+. ./common.rc
|
|
|
9bac43 |
+. ./common.filter
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+_supported_fmt qcow2
|
|
|
9bac43 |
+_supported_proto generic
|
|
|
9bac43 |
+_supported_os Linux
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+size=16M
|
|
|
9bac43 |
+TEST_IMG_BASE=$TEST_IMG.base
|
|
|
9bac43 |
+SECRET0="secret,id=sec0,data=astrochicken"
|
|
|
9bac43 |
+SECRET1="secret,id=sec1,data=furby"
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+TEST_IMG_SAVE=$TEST_IMG
|
|
|
9bac43 |
+TEST_IMG=$TEST_IMG_BASE
|
|
|
9bac43 |
+echo "== create base =="
|
|
|
9bac43 |
+_make_test_img --object $SECRET0 -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10" $size
|
|
|
9bac43 |
+TEST_IMG=$TEST_IMG_SAVE
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+IMGSPECBASE="driver=$IMGFMT,file.filename=$TEST_IMG_BASE,encrypt.key-secret=sec0"
|
|
|
9bac43 |
+IMGSPECLAYER="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec1"
|
|
|
9bac43 |
+IMGSPEC="$IMGSPECLAYER,backing.driver=$IMGFMT,backing.file.filename=$TEST_IMG_BASE,backing.encrypt.key-secret=sec0"
|
|
|
9bac43 |
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo
|
|
|
9bac43 |
+echo "== writing whole image base =="
|
|
|
9bac43 |
+$QEMU_IO --object $SECRET0 -c "write -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo "== create overlay =="
|
|
|
9bac43 |
+_make_test_img --object $SECRET1 -o "encrypt.format=luks,encrypt.key-secret=sec1,encrypt.iter-time=10" -u -b "$TEST_IMG_BASE" $size
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo
|
|
|
9bac43 |
+echo "== writing whole image layer =="
|
|
|
9bac43 |
+$QEMU_IO --object $SECRET0 --object $SECRET1 -c "write -P 0x9 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo
|
|
|
9bac43 |
+echo "== verify pattern base =="
|
|
|
9bac43 |
+$QEMU_IO --object $SECRET0 -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo
|
|
|
9bac43 |
+echo "== verify pattern layer =="
|
|
|
9bac43 |
+$QEMU_IO --object $SECRET0 --object $SECRET1 -c "read -P 0x9 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo
|
|
|
9bac43 |
+echo "== committing layer into base =="
|
|
|
9bac43 |
+$QEMU_IMG commit --object $SECRET0 --object $SECRET1 --image-opts $IMGSPEC | _filter_testdir
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo
|
|
|
9bac43 |
+echo "== verify pattern base =="
|
|
|
9bac43 |
+$QEMU_IO --object $SECRET0 -c "read -P 0x9 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo
|
|
|
9bac43 |
+echo "== verify pattern layer =="
|
|
|
9bac43 |
+$QEMU_IO --object $SECRET0 --object $SECRET1 -c "read -P 0x9 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo
|
|
|
9bac43 |
+echo "== checking image base =="
|
|
|
9bac43 |
+$QEMU_IMG info --image-opts $IMGSPECBASE | _filter_img_info | _filter_testdir | sed -e "/^disk size:/ D"
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+echo
|
|
|
9bac43 |
+echo "== checking image layer =="
|
|
|
9bac43 |
+$QEMU_IMG info --image-opts $IMGSPECLAYER | _filter_img_info | _filter_testdir | sed -e "/^disk size:/ D"
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+# success, all done
|
|
|
9bac43 |
+echo "*** done"
|
|
|
9bac43 |
+rm -f $seq.full
|
|
|
9bac43 |
+status=0
|
|
|
9bac43 |
diff --git a/tests/qemu-iotests/198.out b/tests/qemu-iotests/198.out
|
|
|
9bac43 |
new file mode 100644
|
|
|
9bac43 |
index 0000000..2db565e
|
|
|
9bac43 |
--- /dev/null
|
|
|
9bac43 |
+++ b/tests/qemu-iotests/198.out
|
|
|
9bac43 |
@@ -0,0 +1,126 @@
|
|
|
9bac43 |
+QA output created by 198
|
|
|
9bac43 |
+== create base ==
|
|
|
9bac43 |
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+== writing whole image base ==
|
|
|
9bac43 |
+wrote 16777216/16777216 bytes at offset 0
|
|
|
9bac43 |
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
|
9bac43 |
+== create overlay ==
|
|
|
9bac43 |
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 backing_file=TEST_DIR/t.IMGFMT.base encrypt.format=luks encrypt.key-secret=sec1 encrypt.iter-time=10
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+== writing whole image layer ==
|
|
|
9bac43 |
+wrote 16777216/16777216 bytes at offset 0
|
|
|
9bac43 |
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+== verify pattern base ==
|
|
|
9bac43 |
+read 16777216/16777216 bytes at offset 0
|
|
|
9bac43 |
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+== verify pattern layer ==
|
|
|
9bac43 |
+read 16777216/16777216 bytes at offset 0
|
|
|
9bac43 |
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+== committing layer into base ==
|
|
|
9bac43 |
+Image committed.
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+== verify pattern base ==
|
|
|
9bac43 |
+read 16777216/16777216 bytes at offset 0
|
|
|
9bac43 |
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+== verify pattern layer ==
|
|
|
9bac43 |
+read 16777216/16777216 bytes at offset 0
|
|
|
9bac43 |
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+== checking image base ==
|
|
|
9bac43 |
+image: json:{"encrypt.key-secret": "sec0", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.base"}}
|
|
|
9bac43 |
+file format: IMGFMT
|
|
|
9bac43 |
+virtual size: 16M (16777216 bytes)
|
|
|
9bac43 |
+Format specific information:
|
|
|
9bac43 |
+ compat: 1.1
|
|
|
9bac43 |
+ lazy refcounts: false
|
|
|
9bac43 |
+ refcount bits: 16
|
|
|
9bac43 |
+ encrypt:
|
|
|
9bac43 |
+ ivgen alg: plain64
|
|
|
9bac43 |
+ hash alg: sha256
|
|
|
9bac43 |
+ cipher alg: aes-256
|
|
|
9bac43 |
+ uuid: 00000000-0000-0000-0000-000000000000
|
|
|
9bac43 |
+ format: luks
|
|
|
9bac43 |
+ cipher mode: xts
|
|
|
9bac43 |
+ slots:
|
|
|
9bac43 |
+ [0]:
|
|
|
9bac43 |
+ active: true
|
|
|
9bac43 |
+ iters: 1024
|
|
|
9bac43 |
+ key offset: 4096
|
|
|
9bac43 |
+ stripes: 4000
|
|
|
9bac43 |
+ [1]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 262144
|
|
|
9bac43 |
+ [2]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 520192
|
|
|
9bac43 |
+ [3]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 778240
|
|
|
9bac43 |
+ [4]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 1036288
|
|
|
9bac43 |
+ [5]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 1294336
|
|
|
9bac43 |
+ [6]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 1552384
|
|
|
9bac43 |
+ [7]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 1810432
|
|
|
9bac43 |
+ payload offset: 2068480
|
|
|
9bac43 |
+ master key iters: 1024
|
|
|
9bac43 |
+ corrupt: false
|
|
|
9bac43 |
+
|
|
|
9bac43 |
+== checking image layer ==
|
|
|
9bac43 |
+image: json:{"encrypt.key-secret": "sec1", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}}
|
|
|
9bac43 |
+file format: IMGFMT
|
|
|
9bac43 |
+virtual size: 16M (16777216 bytes)
|
|
|
9bac43 |
+backing file: TEST_DIR/t.IMGFMT.base
|
|
|
9bac43 |
+Format specific information:
|
|
|
9bac43 |
+ compat: 1.1
|
|
|
9bac43 |
+ lazy refcounts: false
|
|
|
9bac43 |
+ refcount bits: 16
|
|
|
9bac43 |
+ encrypt:
|
|
|
9bac43 |
+ ivgen alg: plain64
|
|
|
9bac43 |
+ hash alg: sha256
|
|
|
9bac43 |
+ cipher alg: aes-256
|
|
|
9bac43 |
+ uuid: 00000000-0000-0000-0000-000000000000
|
|
|
9bac43 |
+ format: luks
|
|
|
9bac43 |
+ cipher mode: xts
|
|
|
9bac43 |
+ slots:
|
|
|
9bac43 |
+ [0]:
|
|
|
9bac43 |
+ active: true
|
|
|
9bac43 |
+ iters: 1024
|
|
|
9bac43 |
+ key offset: 4096
|
|
|
9bac43 |
+ stripes: 4000
|
|
|
9bac43 |
+ [1]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 262144
|
|
|
9bac43 |
+ [2]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 520192
|
|
|
9bac43 |
+ [3]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 778240
|
|
|
9bac43 |
+ [4]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 1036288
|
|
|
9bac43 |
+ [5]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 1294336
|
|
|
9bac43 |
+ [6]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 1552384
|
|
|
9bac43 |
+ [7]:
|
|
|
9bac43 |
+ active: false
|
|
|
9bac43 |
+ key offset: 1810432
|
|
|
9bac43 |
+ payload offset: 2068480
|
|
|
9bac43 |
+ master key iters: 1024
|
|
|
9bac43 |
+ corrupt: false
|
|
|
9bac43 |
+*** done
|
|
|
9bac43 |
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
|
|
|
9bac43 |
index 9d5442e..b0140d8 100644
|
|
|
9bac43 |
--- a/tests/qemu-iotests/common.filter
|
|
|
9bac43 |
+++ b/tests/qemu-iotests/common.filter
|
|
|
9bac43 |
@@ -150,7 +150,9 @@ _filter_img_info()
|
|
|
9bac43 |
-e "/lazy_refcounts: \\(on\\|off\\)/d" \
|
|
|
9bac43 |
-e "/block_size: [0-9]\\+/d" \
|
|
|
9bac43 |
-e "/block_state_zero: \\(on\\|off\\)/d" \
|
|
|
9bac43 |
- -e "/log_size: [0-9]\\+/d"
|
|
|
9bac43 |
+ -e "/log_size: [0-9]\\+/d" \
|
|
|
9bac43 |
+ -e "s/iters: [0-9]\\+/iters: 1024/" \
|
|
|
9bac43 |
+ -e "s/uuid: [-a-f0-9]\\+/uuid: 00000000-0000-0000-0000-000000000000/"
|
|
|
9bac43 |
}
|
|
|
9bac43 |
|
|
|
9bac43 |
# filter out offsets and file names from qemu-img map; good for both
|
|
|
9bac43 |
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
|
|
|
9bac43 |
index 0c2bda3..13760b3 100644
|
|
|
9bac43 |
--- a/tests/qemu-iotests/group
|
|
|
9bac43 |
+++ b/tests/qemu-iotests/group
|
|
|
9bac43 |
@@ -188,3 +188,4 @@
|
|
|
9bac43 |
190 rw auto quick
|
|
|
9bac43 |
192 rw auto quick
|
|
|
9bac43 |
194 rw auto migration quick
|
|
|
9bac43 |
+198 rw auto
|
|
|
9bac43 |
--
|
|
|
9bac43 |
1.8.3.1
|
|
|
9bac43 |
|