* Thu Sep 26 2019 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 4.1.0-12.el8
- kvm-block-Use-QEMU_IS_ALIGNED.patch [bz#1745922] - kvm-block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch [bz#1745922] - kvm-block-qcow2-refactor-encryption-code.patch [bz#1745922] - kvm-qemu-iotests-Add-test-for-bz-1745922.patch [bz#1745922] - Resolves: bz#1745922 (Luks-inside-qcow2 snapshot cannot boot after 'qemu-img rebase')
This commit is contained in:
parent
58b71dc108
commit
4172d6971a
192
kvm-block-Use-QEMU_IS_ALIGNED.patch
Normal file
192
kvm-block-Use-QEMU_IS_ALIGNED.patch
Normal file
@ -0,0 +1,192 @@
|
||||
From 1eb1c45037b1e1084ab601ac8461fabca162b479 Mon Sep 17 00:00:00 2001
|
||||
From: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Date: Tue, 24 Sep 2019 21:11:49 +0100
|
||||
Subject: [PATCH 1/4] block: Use QEMU_IS_ALIGNED
|
||||
|
||||
RH-Author: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Message-id: <20190924211152.13461-2-mlevitsk@redhat.com>
|
||||
Patchwork-id: 90874
|
||||
O-Subject: [RHEL-AV-8.1.0 qemu-kvm PATCH v2 1/4] block: Use QEMU_IS_ALIGNED
|
||||
Bugzilla: 1745922
|
||||
RH-Acked-by: John Snow <jsnow@redhat.com>
|
||||
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
||||
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
|
||||
|
||||
From: Nir Soffer <nirsof@gmail.com>
|
||||
|
||||
Replace instances of:
|
||||
|
||||
(n & (BDRV_SECTOR_SIZE - 1)) == 0
|
||||
|
||||
And:
|
||||
|
||||
(n & ~BDRV_SECTOR_MASK) == 0
|
||||
|
||||
With:
|
||||
|
||||
QEMU_IS_ALIGNED(n, BDRV_SECTOR_SIZE)
|
||||
|
||||
Which reveals the intent of the code better, and makes it easier to
|
||||
locate the code checking alignment.
|
||||
|
||||
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
|
||||
Message-id: 20190827185913.27427-2-nsoffer@redhat.com
|
||||
Reviewed-by: John Snow <jsnow@redhat.com>
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
(cherry picked from commit 1bbbf32d5fffe334531c315d7bd865fdfb67b6c5)
|
||||
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||
---
|
||||
block/bochs.c | 4 ++--
|
||||
block/cloop.c | 4 ++--
|
||||
block/dmg.c | 4 ++--
|
||||
block/io.c | 8 ++++----
|
||||
block/qcow2-cluster.c | 4 ++--
|
||||
block/qcow2.c | 4 ++--
|
||||
block/vvfat.c | 8 ++++----
|
||||
qemu-img.c | 2 +-
|
||||
8 files changed, 19 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/block/bochs.c b/block/bochs.c
|
||||
index 962f185..32bb83b 100644
|
||||
--- a/block/bochs.c
|
||||
+++ b/block/bochs.c
|
||||
@@ -248,8 +248,8 @@ bochs_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
QEMUIOVector local_qiov;
|
||||
int ret;
|
||||
|
||||
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
|
||||
qemu_iovec_init(&local_qiov, qiov->niov);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
diff --git a/block/cloop.c b/block/cloop.c
|
||||
index 384c973..4de9487 100644
|
||||
--- a/block/cloop.c
|
||||
+++ b/block/cloop.c
|
||||
@@ -253,8 +253,8 @@ cloop_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
|
||||
int ret, i;
|
||||
|
||||
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
|
||||
diff --git a/block/dmg.c b/block/dmg.c
|
||||
index 45f6b28..4a045f2 100644
|
||||
--- a/block/dmg.c
|
||||
+++ b/block/dmg.c
|
||||
@@ -697,8 +697,8 @@ dmg_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
|
||||
int ret, i;
|
||||
|
||||
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
|
||||
diff --git a/block/io.c b/block/io.c
|
||||
index 06305c6..54093fc 100644
|
||||
--- a/block/io.c
|
||||
+++ b/block/io.c
|
||||
@@ -1079,8 +1079,8 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
|
||||
sector_num = offset >> BDRV_SECTOR_BITS;
|
||||
nb_sectors = bytes >> BDRV_SECTOR_BITS;
|
||||
|
||||
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
assert(bytes <= BDRV_REQUEST_MAX_BYTES);
|
||||
assert(drv->bdrv_co_readv);
|
||||
|
||||
@@ -1132,8 +1132,8 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
|
||||
sector_num = offset >> BDRV_SECTOR_BITS;
|
||||
nb_sectors = bytes >> BDRV_SECTOR_BITS;
|
||||
|
||||
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
assert(bytes <= BDRV_REQUEST_MAX_BYTES);
|
||||
|
||||
assert(drv->bdrv_co_writev);
|
||||
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
|
||||
index cc5609e..f2de746 100644
|
||||
--- a/block/qcow2-cluster.c
|
||||
+++ b/block/qcow2-cluster.c
|
||||
@@ -470,8 +470,8 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
|
||||
{
|
||||
if (bytes && bs->encrypted) {
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
- assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);
|
||||
- assert((bytes & ~BDRV_SECTOR_MASK) == 0);
|
||||
+ assert(QEMU_IS_ALIGNED(offset_in_cluster, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
assert(s->crypto);
|
||||
if (qcow2_co_encrypt(bs, cluster_offset,
|
||||
src_cluster_offset + offset_in_cluster,
|
||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||
index 039bdc2..dc4302f 100644
|
||||
--- a/block/qcow2.c
|
||||
+++ b/block/qcow2.c
|
||||
@@ -2071,8 +2071,8 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
|
||||
}
|
||||
if (bs->encrypted) {
|
||||
assert(s->crypto);
|
||||
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
- assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(cur_bytes, BDRV_SECTOR_SIZE));
|
||||
if (qcow2_co_decrypt(bs, cluster_offset, offset,
|
||||
cluster_data, cur_bytes) < 0) {
|
||||
ret = -EIO;
|
||||
diff --git a/block/vvfat.c b/block/vvfat.c
|
||||
index f6c2880..019b8f1 100644
|
||||
--- a/block/vvfat.c
|
||||
+++ b/block/vvfat.c
|
||||
@@ -1547,8 +1547,8 @@ vvfat_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
|
||||
void *buf;
|
||||
|
||||
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
|
||||
buf = g_try_malloc(bytes);
|
||||
if (bytes && buf == NULL) {
|
||||
@@ -3082,8 +3082,8 @@ vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
|
||||
void *buf;
|
||||
|
||||
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
|
||||
buf = g_try_malloc(bytes);
|
||||
if (bytes && buf == NULL) {
|
||||
diff --git a/qemu-img.c b/qemu-img.c
|
||||
index 7998377..940ae94 100644
|
||||
--- a/qemu-img.c
|
||||
+++ b/qemu-img.c
|
||||
@@ -2138,7 +2138,7 @@ static int img_convert(int argc, char **argv)
|
||||
int64_t sval;
|
||||
|
||||
sval = cvtnum(optarg);
|
||||
- if (sval < 0 || sval & (BDRV_SECTOR_SIZE - 1) ||
|
||||
+ if (sval < 0 || !QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) ||
|
||||
sval / BDRV_SECTOR_SIZE > MAX_BUF_SECTORS) {
|
||||
error_report("Invalid buffer size for sparse output specified. "
|
||||
"Valid sizes are multiples of %llu up to %llu. Select "
|
||||
--
|
||||
1.8.3.1
|
||||
|
@ -0,0 +1,78 @@
|
||||
From 554884a1fe9a271ad78771c37e4be5a8f84258fc Mon Sep 17 00:00:00 2001
|
||||
From: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Date: Tue, 24 Sep 2019 21:11:50 +0100
|
||||
Subject: [PATCH 2/4] block/qcow2: Fix corruption introduced by commit
|
||||
8ac0f15f335
|
||||
|
||||
RH-Author: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Message-id: <20190924211152.13461-3-mlevitsk@redhat.com>
|
||||
Patchwork-id: 90878
|
||||
O-Subject: [RHEL-AV-8.1.0 qemu-kvm PATCH v2 2/4] block/qcow2: Fix corruption introduced by commit 8ac0f15f335
|
||||
Bugzilla: 1745922
|
||||
RH-Acked-by: John Snow <jsnow@redhat.com>
|
||||
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
||||
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
|
||||
|
||||
This fixes subtle corruption introduced by luks threaded encryption
|
||||
in commit 8ac0f15f335
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1745922
|
||||
|
||||
The corruption happens when we do a write that
|
||||
* writes to two or more unallocated clusters at once
|
||||
* doesn't fully cover the first sector
|
||||
* doesn't fully cover the last sector
|
||||
* uses luks encryption
|
||||
|
||||
In this case, when allocating the new clusters we COW both areas
|
||||
prior to the write and after the write, and we encrypt them.
|
||||
|
||||
The above mentioned commit accidentally made it so we encrypt the
|
||||
second COW area using the physical cluster offset of the first area.
|
||||
|
||||
The problem is that offset_in_cluster in do_perform_cow_encrypt
|
||||
can be larger that the cluster size, thus cluster_offset
|
||||
will no longer point to the start of the cluster at which encrypted
|
||||
area starts.
|
||||
|
||||
Next patch in this series will refactor the code to avoid all these
|
||||
assumptions.
|
||||
|
||||
In the bugreport that was triggered by rebasing a luks image to new,
|
||||
zero filled base, which lot of such writes, and causes some files
|
||||
with zero areas to contain garbage there instead.
|
||||
But as described above it can happen elsewhere as well
|
||||
|
||||
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||
Message-id: 20190915203655.21638-2-mlevitsk@redhat.com
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
(cherry picked from commit 38e7d54bdc518b5a05a922467304bcace2396945)
|
||||
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||
---
|
||||
block/qcow2-cluster.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
|
||||
index f2de746..11e5a92 100644
|
||||
--- a/block/qcow2-cluster.c
|
||||
+++ b/block/qcow2-cluster.c
|
||||
@@ -473,9 +473,10 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
|
||||
assert(QEMU_IS_ALIGNED(offset_in_cluster, BDRV_SECTOR_SIZE));
|
||||
assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
assert(s->crypto);
|
||||
- if (qcow2_co_encrypt(bs, cluster_offset,
|
||||
- src_cluster_offset + offset_in_cluster,
|
||||
- buffer, bytes) < 0) {
|
||||
+ if (qcow2_co_encrypt(bs,
|
||||
+ start_of_cluster(s, cluster_offset + offset_in_cluster),
|
||||
+ src_cluster_offset + offset_in_cluster,
|
||||
+ buffer, bytes) < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
--
|
||||
1.8.3.1
|
||||
|
234
kvm-block-qcow2-refactor-encryption-code.patch
Normal file
234
kvm-block-qcow2-refactor-encryption-code.patch
Normal file
@ -0,0 +1,234 @@
|
||||
From 780fbdf04884188eca3d5891faa2b2417a88ef14 Mon Sep 17 00:00:00 2001
|
||||
From: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Date: Tue, 24 Sep 2019 21:11:51 +0100
|
||||
Subject: [PATCH 3/4] block/qcow2: refactor encryption code
|
||||
|
||||
RH-Author: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Message-id: <20190924211152.13461-4-mlevitsk@redhat.com>
|
||||
Patchwork-id: 90876
|
||||
O-Subject: [RHEL-AV-8.1.0 qemu-kvm PATCH v2 3/4] block/qcow2: refactor encryption code
|
||||
Bugzilla: 1745922
|
||||
RH-Acked-by: John Snow <jsnow@redhat.com>
|
||||
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
||||
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
|
||||
|
||||
* Change the qcow2_co_{encrypt|decrypt} to just receive full host and
|
||||
guest offsets and use this function directly instead of calling
|
||||
do_perform_cow_encrypt (which is removed by that patch).
|
||||
|
||||
* Adjust qcow2_co_encdec to take full host and guest offsets as well.
|
||||
|
||||
* Document the qcow2_co_{encrypt|decrypt} arguments
|
||||
to prevent the bug fixed in former commit from hopefully
|
||||
happening again.
|
||||
|
||||
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Message-id: 20190915203655.21638-3-mlevitsk@redhat.com
|
||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||
[mreitz: Let perform_cow() return the error value returned by
|
||||
qcow2_co_encrypt(), as proposed by Vladimir]
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
(cherry picked from commit 603fbd076c76438b15ec842f0e2d1ba4867dfd00)
|
||||
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
|
||||
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||
---
|
||||
block/qcow2-cluster.c | 41 +++++++++++----------------------
|
||||
block/qcow2-threads.c | 63 +++++++++++++++++++++++++++++++++++++++------------
|
||||
block/qcow2.c | 5 ++--
|
||||
block/qcow2.h | 8 +++----
|
||||
4 files changed, 69 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
|
||||
index 11e5a92..b30fd12 100644
|
||||
--- a/block/qcow2-cluster.c
|
||||
+++ b/block/qcow2-cluster.c
|
||||
@@ -461,28 +461,6 @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
|
||||
- uint64_t src_cluster_offset,
|
||||
- uint64_t cluster_offset,
|
||||
- unsigned offset_in_cluster,
|
||||
- uint8_t *buffer,
|
||||
- unsigned bytes)
|
||||
-{
|
||||
- if (bytes && bs->encrypted) {
|
||||
- BDRVQcow2State *s = bs->opaque;
|
||||
- assert(QEMU_IS_ALIGNED(offset_in_cluster, BDRV_SECTOR_SIZE));
|
||||
- assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
|
||||
- assert(s->crypto);
|
||||
- if (qcow2_co_encrypt(bs,
|
||||
- start_of_cluster(s, cluster_offset + offset_in_cluster),
|
||||
- src_cluster_offset + offset_in_cluster,
|
||||
- buffer, bytes) < 0) {
|
||||
- return false;
|
||||
- }
|
||||
- }
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
|
||||
uint64_t cluster_offset,
|
||||
unsigned offset_in_cluster,
|
||||
@@ -887,12 +865,19 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
|
||||
|
||||
/* Encrypt the data if necessary before writing it */
|
||||
if (bs->encrypted) {
|
||||
- if (!do_perform_cow_encrypt(bs, m->offset, m->alloc_offset,
|
||||
- start->offset, start_buffer,
|
||||
- start->nb_bytes) ||
|
||||
- !do_perform_cow_encrypt(bs, m->offset, m->alloc_offset,
|
||||
- end->offset, end_buffer, end->nb_bytes)) {
|
||||
- ret = -EIO;
|
||||
+ ret = qcow2_co_encrypt(bs,
|
||||
+ m->alloc_offset + start->offset,
|
||||
+ m->offset + start->offset,
|
||||
+ start_buffer, start->nb_bytes);
|
||||
+ if (ret < 0) {
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ ret = qcow2_co_encrypt(bs,
|
||||
+ m->alloc_offset + end->offset,
|
||||
+ m->offset + end->offset,
|
||||
+ end_buffer, end->nb_bytes);
|
||||
+ if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c
|
||||
index 3b1e63f..8f5a0d1 100644
|
||||
--- a/block/qcow2-threads.c
|
||||
+++ b/block/qcow2-threads.c
|
||||
@@ -234,35 +234,70 @@ static int qcow2_encdec_pool_func(void *opaque)
|
||||
}
|
||||
|
||||
static int coroutine_fn
|
||||
-qcow2_co_encdec(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||
- uint64_t offset, void *buf, size_t len, Qcow2EncDecFunc func)
|
||||
+qcow2_co_encdec(BlockDriverState *bs, uint64_t host_offset,
|
||||
+ uint64_t guest_offset, void *buf, size_t len,
|
||||
+ Qcow2EncDecFunc func)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
Qcow2EncDecData arg = {
|
||||
.block = s->crypto,
|
||||
- .offset = s->crypt_physical_offset ?
|
||||
- file_cluster_offset + offset_into_cluster(s, offset) :
|
||||
- offset,
|
||||
+ .offset = s->crypt_physical_offset ? host_offset : guest_offset,
|
||||
.buf = buf,
|
||||
.len = len,
|
||||
.func = func,
|
||||
};
|
||||
|
||||
- return qcow2_co_process(bs, qcow2_encdec_pool_func, &arg);
|
||||
+ assert(QEMU_IS_ALIGNED(guest_offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(host_offset, BDRV_SECTOR_SIZE));
|
||||
+ assert(QEMU_IS_ALIGNED(len, BDRV_SECTOR_SIZE));
|
||||
+ assert(s->crypto);
|
||||
+
|
||||
+ return len == 0 ? 0 : qcow2_co_process(bs, qcow2_encdec_pool_func, &arg);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * qcow2_co_encrypt()
|
||||
+ *
|
||||
+ * Encrypts one or more contiguous aligned sectors
|
||||
+ *
|
||||
+ * @host_offset - underlying storage offset of the first sector of the
|
||||
+ * data to be encrypted
|
||||
+ *
|
||||
+ * @guest_offset - guest (virtual) offset of the first sector of the
|
||||
+ * data to be encrypted
|
||||
+ *
|
||||
+ * @buf - buffer with the data to encrypt, that after encryption
|
||||
+ * will be written to the underlying storage device at
|
||||
+ * @host_offset
|
||||
+ *
|
||||
+ * @len - length of the buffer (must be a BDRV_SECTOR_SIZE multiple)
|
||||
+ *
|
||||
+ * Depending on the encryption method, @host_offset and/or @guest_offset
|
||||
+ * may be used for generating the initialization vector for
|
||||
+ * encryption.
|
||||
+ *
|
||||
+ * Note that while the whole range must be aligned on sectors, it
|
||||
+ * does not have to be aligned on clusters and can also cross cluster
|
||||
+ * boundaries
|
||||
+ */
|
||||
int coroutine_fn
|
||||
-qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||
- uint64_t offset, void *buf, size_t len)
|
||||
+qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset,
|
||||
+ uint64_t guest_offset, void *buf, size_t len)
|
||||
{
|
||||
- return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len,
|
||||
- qcrypto_block_encrypt);
|
||||
+ return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
|
||||
+ qcrypto_block_encrypt);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * qcow2_co_decrypt()
|
||||
+ *
|
||||
+ * Decrypts one or more contiguous aligned sectors
|
||||
+ * Similar to qcow2_co_encrypt
|
||||
+ */
|
||||
int coroutine_fn
|
||||
-qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||
- uint64_t offset, void *buf, size_t len)
|
||||
+qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset,
|
||||
+ uint64_t guest_offset, void *buf, size_t len)
|
||||
{
|
||||
- return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len,
|
||||
- qcrypto_block_decrypt);
|
||||
+ return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
|
||||
+ qcrypto_block_decrypt);
|
||||
}
|
||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||
index dc4302f..d4c4f24 100644
|
||||
--- a/block/qcow2.c
|
||||
+++ b/block/qcow2.c
|
||||
@@ -2073,7 +2073,8 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
|
||||
assert(s->crypto);
|
||||
assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
|
||||
assert(QEMU_IS_ALIGNED(cur_bytes, BDRV_SECTOR_SIZE));
|
||||
- if (qcow2_co_decrypt(bs, cluster_offset, offset,
|
||||
+ if (qcow2_co_decrypt(bs, cluster_offset + offset_in_cluster,
|
||||
+ offset,
|
||||
cluster_data, cur_bytes) < 0) {
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
@@ -2288,7 +2289,7 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
|
||||
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
|
||||
qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);
|
||||
|
||||
- if (qcow2_co_encrypt(bs, cluster_offset, offset,
|
||||
+ if (qcow2_co_encrypt(bs, cluster_offset + offset_in_cluster, offset,
|
||||
cluster_data, cur_bytes) < 0) {
|
||||
ret = -EIO;
|
||||
goto out_unlocked;
|
||||
diff --git a/block/qcow2.h b/block/qcow2.h
|
||||
index fc1b0d3..b54e734 100644
|
||||
--- a/block/qcow2.h
|
||||
+++ b/block/qcow2.h
|
||||
@@ -757,10 +757,10 @@ ssize_t coroutine_fn
|
||||
qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
|
||||
const void *src, size_t src_size);
|
||||
int coroutine_fn
|
||||
-qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||
- uint64_t offset, void *buf, size_t len);
|
||||
+qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset,
|
||||
+ uint64_t guest_offset, void *buf, size_t len);
|
||||
int coroutine_fn
|
||||
-qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||
- uint64_t offset, void *buf, size_t len);
|
||||
+qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset,
|
||||
+ uint64_t guest_offset, void *buf, size_t len);
|
||||
|
||||
#endif
|
||||
--
|
||||
1.8.3.1
|
||||
|
191
kvm-qemu-iotests-Add-test-for-bz-1745922.patch
Normal file
191
kvm-qemu-iotests-Add-test-for-bz-1745922.patch
Normal file
@ -0,0 +1,191 @@
|
||||
From a888b935e29a08f0ace84906fee84b41a5f8b95d Mon Sep 17 00:00:00 2001
|
||||
From: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Date: Tue, 24 Sep 2019 21:11:52 +0100
|
||||
Subject: [PATCH 4/4] qemu-iotests: Add test for bz #1745922
|
||||
|
||||
RH-Author: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Message-id: <20190924211152.13461-5-mlevitsk@redhat.com>
|
||||
Patchwork-id: 90877
|
||||
O-Subject: [RHEL-AV-8.1.0 qemu-kvm PATCH v2 4/4] qemu-iotests: Add test for bz #1745922
|
||||
Bugzilla: 1745922
|
||||
RH-Acked-by: John Snow <jsnow@redhat.com>
|
||||
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
||||
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
|
||||
|
||||
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
Tested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||
Message-id: 20190915203655.21638-4-mlevitsk@redhat.com
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
(cherry picked from commit 1825cc0783ccf0ec5d9f0b225a99b340bdd4c68f)
|
||||
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
tests/qemu-iotests/group
|
||||
usual conflicts with missing tests
|
||||
|
||||
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||
---
|
||||
tests/qemu-iotests/263 | 91 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
tests/qemu-iotests/263.out | 40 ++++++++++++++++++++
|
||||
tests/qemu-iotests/group | 1 +
|
||||
3 files changed, 132 insertions(+)
|
||||
create mode 100755 tests/qemu-iotests/263
|
||||
create mode 100644 tests/qemu-iotests/263.out
|
||||
|
||||
diff --git a/tests/qemu-iotests/263 b/tests/qemu-iotests/263
|
||||
new file mode 100755
|
||||
index 0000000..d2c030f
|
||||
--- /dev/null
|
||||
+++ b/tests/qemu-iotests/263
|
||||
@@ -0,0 +1,91 @@
|
||||
+#!/usr/bin/env bash
|
||||
+#
|
||||
+# Test encrypted write that crosses cluster boundary of two unallocated clusters
|
||||
+# Based on 188
|
||||
+#
|
||||
+# Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
|
||||
+#
|
||||
+
|
||||
+# creator
|
||||
+owner=mlevitsk@redhat.com
|
||||
+
|
||||
+seq=`basename $0`
|
||||
+echo "QA output created by $seq"
|
||||
+
|
||||
+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
|
||||
+
|
||||
+
|
||||
+size=1M
|
||||
+
|
||||
+SECRET="secret,id=sec0,data=astrochicken"
|
||||
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
||||
+
|
||||
+
|
||||
+_run_test()
|
||||
+{
|
||||
+ echo "== reading the whole image =="
|
||||
+ $QEMU_IO --object $SECRET -c "read -P 0 0 $size" --image-opts "$1" | _filter_qemu_io | _filter_testdir
|
||||
+
|
||||
+ echo
|
||||
+ echo "== write two 512 byte sectors on a cluster boundary =="
|
||||
+ $QEMU_IO --object $SECRET -c "write -P 0xAA 0xFE00 0x400" --image-opts "$1" | _filter_qemu_io | _filter_testdir
|
||||
+
|
||||
+ echo
|
||||
+ echo "== verify that the rest of the image is not changed =="
|
||||
+ $QEMU_IO --object $SECRET -c "read -P 0x00 0x00000 0xFE00" --image-opts "$1" | _filter_qemu_io | _filter_testdir
|
||||
+ $QEMU_IO --object $SECRET -c "read -P 0xAA 0x0FE00 0x400" --image-opts "$1" | _filter_qemu_io | _filter_testdir
|
||||
+ $QEMU_IO --object $SECRET -c "read -P 0x00 0x10200 0xEFE00" --image-opts "$1" | _filter_qemu_io | _filter_testdir
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+echo
|
||||
+echo "testing LUKS qcow2 encryption"
|
||||
+echo
|
||||
+
|
||||
+_make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,cluster_size=64K" $size
|
||||
+_run_test "driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG"
|
||||
+_cleanup_test_img
|
||||
+
|
||||
+echo
|
||||
+echo "testing legacy AES qcow2 encryption"
|
||||
+echo
|
||||
+
|
||||
+
|
||||
+_make_test_img --object $SECRET -o "encrypt.format=aes,encrypt.key-secret=sec0,cluster_size=64K" $size
|
||||
+_run_test "driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG"
|
||||
+_cleanup_test_img
|
||||
+
|
||||
+
|
||||
+
|
||||
+# success, all done
|
||||
+echo "*** done"
|
||||
+rm -f $seq.full
|
||||
+status=0
|
||||
diff --git a/tests/qemu-iotests/263.out b/tests/qemu-iotests/263.out
|
||||
new file mode 100644
|
||||
index 0000000..0c982c5
|
||||
--- /dev/null
|
||||
+++ b/tests/qemu-iotests/263.out
|
||||
@@ -0,0 +1,40 @@
|
||||
+QA output created by 263
|
||||
+
|
||||
+testing LUKS qcow2 encryption
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
|
||||
+== reading the whole image ==
|
||||
+read 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+
|
||||
+== write two 512 byte sectors on a cluster boundary ==
|
||||
+wrote 1024/1024 bytes at offset 65024
|
||||
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+
|
||||
+== verify that the rest of the image is not changed ==
|
||||
+read 65024/65024 bytes at offset 0
|
||||
+63.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+read 1024/1024 bytes at offset 65024
|
||||
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+read 982528/982528 bytes at offset 66048
|
||||
+959.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+
|
||||
+testing legacy AES qcow2 encryption
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=aes encrypt.key-secret=sec0
|
||||
+== reading the whole image ==
|
||||
+read 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+
|
||||
+== write two 512 byte sectors on a cluster boundary ==
|
||||
+wrote 1024/1024 bytes at offset 65024
|
||||
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+
|
||||
+== verify that the rest of the image is not changed ==
|
||||
+read 65024/65024 bytes at offset 0
|
||||
+63.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+read 1024/1024 bytes at offset 65024
|
||||
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+read 982528/982528 bytes at offset 66048
|
||||
+959.500 KiB, 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 813db25..4a7e08f 100644
|
||||
--- a/tests/qemu-iotests/group
|
||||
+++ b/tests/qemu-iotests/group
|
||||
@@ -271,3 +271,4 @@
|
||||
254 rw backing quick
|
||||
255 rw quick
|
||||
256 rw quick
|
||||
+263 rw quick
|
||||
\ No newline at end of file
|
||||
--
|
||||
1.8.3.1
|
||||
|
@ -67,7 +67,7 @@ Obsoletes: %1-rhev
|
||||
Summary: QEMU is a machine emulator and virtualizer
|
||||
Name: qemu-kvm
|
||||
Version: 4.1.0
|
||||
Release: 11%{?dist}
|
||||
Release: 12%{?dist}
|
||||
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
|
||||
Epoch: 15
|
||||
License: GPLv2 and GPLv2+ and CC-BY
|
||||
@ -208,6 +208,14 @@ Patch61: kvm-hostmem-file-fix-pmem-file-size-check.patch
|
||||
Patch62: kvm-memory-fetch-pmem-size-in-get_file_size.patch
|
||||
# For bz#1753992 - core dump when testing persistent reservation in guest
|
||||
Patch63: kvm-pr-manager-Fix-invalid-g_free-crash-bug.patch
|
||||
# For bz#1745922 - Luks-inside-qcow2 snapshot cannot boot after 'qemu-img rebase'
|
||||
Patch64: kvm-block-Use-QEMU_IS_ALIGNED.patch
|
||||
# For bz#1745922 - Luks-inside-qcow2 snapshot cannot boot after 'qemu-img rebase'
|
||||
Patch65: kvm-block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch
|
||||
# For bz#1745922 - Luks-inside-qcow2 snapshot cannot boot after 'qemu-img rebase'
|
||||
Patch66: kvm-block-qcow2-refactor-encryption-code.patch
|
||||
# For bz#1745922 - Luks-inside-qcow2 snapshot cannot boot after 'qemu-img rebase'
|
||||
Patch67: kvm-qemu-iotests-Add-test-for-bz-1745922.patch
|
||||
|
||||
BuildRequires: wget
|
||||
BuildRequires: rpm-build
|
||||
@ -1149,6 +1157,14 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Sep 26 2019 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 4.1.0-12.el8
|
||||
- kvm-block-Use-QEMU_IS_ALIGNED.patch [bz#1745922]
|
||||
- kvm-block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch [bz#1745922]
|
||||
- kvm-block-qcow2-refactor-encryption-code.patch [bz#1745922]
|
||||
- kvm-qemu-iotests-Add-test-for-bz-1745922.patch [bz#1745922]
|
||||
- Resolves: bz#1745922
|
||||
(Luks-inside-qcow2 snapshot cannot boot after 'qemu-img rebase')
|
||||
|
||||
* Mon Sep 23 2019 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 4.1.0-11.el8
|
||||
- kvm-blockjob-update-nodes-head-while-removing-all-bdrv.patch [bz#1746631]
|
||||
- kvm-hostmem-file-fix-pmem-file-size-check.patch [bz#1724008 bz#1736788]
|
||||
|
Loading…
Reference in New Issue
Block a user