Skip to contentSkip to conversation

Misc fixes and testing of qcow[2] encryption

PATCH Applied Daniel P. Berrange 5 participants 17 messages May 12, 2015 – May 18, 2015 Block layer

lore
Share & tools
lore
#0 lore raw

cover Misc fixes and testing of qcow[2] encryption

I realize that qcow[2] encryption is a feature we have deprecated and will remove support for running it with the QEMU system emulators in this cycle. We do still need to make sure it continues to work for the sake of letting people run qemu-img convert to retrieve their data though.

Some of the other patches I'm working on which introduce a cypto cipher API touch this qcow2 code, thus I wanted to be able to test that it doesn't break anything.

I found that qemu-iotests didn't have any coverage of the qcow2 encryption code. For added fun, I then discovered that qemu-io doesn't check if an encryption key is required, so ends up writing plain text to the files instead of cipher, and returning cipher text for reads, instead of plain text. IOW qemu-io will corrupt encrypted qcow2 files on write.

This series adds some asserts that will protect against this kind of mistake, adds support for getting passwords to qemu-io (in the same manner that qemu-img supports), and finally adds a test case for reading/writing encrypted qcow2.

Daniel P. Berrange (5):
qcow2/qcow: protect against uninitialized encryption key
util: move read_password method out of qemu-img into osdep/oslib
util: allow \n to terminate password input
qemu-io: prompt for encryption keys when required
tests: add test case for encrypted qcow2 read/write

 block/qcow.c               | 10 +++--
 block/qcow2-cluster.c      |  3 +-
 block/qcow2.c              | 18 ++++++---
 include/qemu/osdep.h       |  2 +
 qemu-img.c                 | 93 +---------------------------------------------
 qemu-io.c                  | 21 +++++++++++
 tests/qemu-iotests/131     | 69 ++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/131.out | 46 +++++++++++++++++++++++
 tests/qemu-iotests/group   |  1 +
 util/oslib-posix.c         | 67 +++++++++++++++++++++++++++++++++
 util/oslib-win32.c         | 24 ++++++++++++
 11 files changed, 252 insertions(+), 102 deletions(-)
 create mode 100755 tests/qemu-iotests/131
 create mode 100644 tests/qemu-iotests/131.out
Signature · 1 line
2.1.0
#1 lore raw

PATCH 1/5 qcow2/qcow: protect against uninitialized encryption key

When a qcow[2] file is opened, if the header reports an encryption method, this is used to set the 'crypt_method_header' field on the BDRVQcow[2]State struct, and the 'encrypted' flag in the BDRVState struct.

When doing I/O operations, the 'crypt_method' field on the BDRVQcow[2]State struct is checked to determine if encryption needs to be applied.

The crypt_method_header value is copied into crypt_method when the bdrv_set_key() method is called.

The QEMU code which opens a block device is expected to always do a check

   if (bdrv_is_encrypted(bs)) {
       bdrv_set_key(bs, ....key...);
   }

If code forgets todo this, then 'crypt_method' is never set and so when I/O is performed, QEMU writes plain text data into a sector which is expected to contain cipher text, or when reading, will return cipher text instead of plain text.

Change the qcow[2] code to consult bs->encrypted when deciding whether encryption is required, and assert(s->crypt_method) to protect against cases where the caller forgets to set the encryption key.

Also put an assert in the set_key methods to protect against the case where the caller sets an encryption key on a block device that does not have encryption

---
 block/qcow.c          | 10 +++++++---
 block/qcow2-cluster.c |  3 ++-
 block/qcow2.c         | 18 ++++++++++++------
 3 files changed, 21 insertions(+), 10 deletions(-)
block/qcow.c +7 -3
index ab89328..911e59f 100644
@@ -269,6 +269,7 @@ static int qcow_set_key(BlockDriverState *bs, const char *key)
     for(i = 0;i < len;i++) {
         keybuf[i] = key[i];
     }
+    assert(bs->encrypted);
     s->crypt_method = s->crypt_method_header;
 
     if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0)
@@ -411,9 +412,10 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
                 bdrv_truncate(bs->file, cluster_offset + s->cluster_size);
                 /* if encrypted, we must initialize the cluster
                    content which won't be written */
-                if (s->crypt_method &&
+                if (bs->encrypted &&
                     (n_end - n_start) < s->cluster_sectors) {
                     uint64_t start_sect;
+                    assert(s->crypt_method);
                     start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
                     memset(s->cluster_data + 512, 0x00, 512);
                     for(i = 0; i < s->cluster_sectors; i++) {
@@ -590,7 +592,8 @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
             if (ret < 0) {
                 break;
             }
-            if (s->crypt_method) {
+            if (bs->encrypted) {
+                assert(s->crypt_method);
                 encrypt_sectors(s, sector_num, buf, buf,
                                 n, 0,
                                 &s->aes_decrypt_key);
@@ -661,7 +664,8 @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
             ret = -EIO;
             break;
         }
-        if (s->crypt_method) {
+        if (bs->encrypted) {
+            assert(s->crypt_method);
             if (!cluster_data) {
                 cluster_data = g_malloc0(s->cluster_size);
             }
block/qcow2-cluster.c +2 -1
index ed2b44d..2d7777d 100644
@@ -403,7 +403,8 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
         goto out;
     }
 
-    if (s->crypt_method) {
+    if (bs->encrypted) {
+        assert(s->crypt_method);
         qcow2_encrypt_sectors(s, start_sect + n_start,
                         iov.iov_base, iov.iov_base, n, 1,
                         &s->aes_encrypt_key);
block/qcow2.c +12 -6
index b9a72e3..f7b4cc6 100644
@@ -1037,6 +1037,7 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key)
     for(i = 0;i < len;i++) {
         keybuf[i] = key[i];
     }
+    assert(bs->encrypted);
     s->crypt_method = s->crypt_method_header;
 
     if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0)
@@ -1224,7 +1225,9 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,
                 goto fail;
             }
 
-            if (s->crypt_method) {
+            if (bs->encrypted) {
+                assert(s->crypt_method);
+
                 /*
                  * For encrypted images, read everything into a temporary
                  * contiguous buffer on which the AES functions can work.
@@ -1255,7 +1258,8 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,
             if (ret < 0) {
                 goto fail;
             }
-            if (s->crypt_method) {
+            if (bs->encrypted) {
+                assert(s->crypt_method);
                 qcow2_encrypt_sectors(s, sector_num,  cluster_data,
                     cluster_data, cur_nr_sectors, 0, &s->aes_decrypt_key);
                 qemu_iovec_from_buf(qiov, bytes_done,
@@ -1315,7 +1319,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
         trace_qcow2_writev_start_part(qemu_coroutine_self());
         index_in_cluster = sector_num & (s->cluster_sectors - 1);
         cur_nr_sectors = remaining_sectors;
-        if (s->crypt_method &&
+        if (bs->encrypted &&
             cur_nr_sectors >
             QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster) {
             cur_nr_sectors =
@@ -1334,7 +1338,8 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
         qemu_iovec_concat(&hd_qiov, qiov, bytes_done,
             cur_nr_sectors * 512);
 
-        if (s->crypt_method) {
+        if (bs->encrypted) {
+            assert(s->crypt_method);
             if (!cluster_data) {
                 cluster_data = qemu_try_blockalign(bs->file,
                                                    QCOW_MAX_CRYPT_CLUSTERS
@@ -1484,7 +1489,8 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
      * that means we don't have to worry about reopening them here.
      */
 
-    if (s->crypt_method) {
+    if (bs->encrypted) {
+        assert(s->crypt_method);
         crypt_method = s->crypt_method;
         memcpy(&aes_encrypt_key, &s->aes_encrypt_key, sizeof(aes_encrypt_key));
         memcpy(&aes_decrypt_key, &s->aes_decrypt_key, sizeof(aes_decrypt_key));
@@ -1513,7 +1519,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
         return;
     }
 
-    if (crypt_method) {
+    if (bs->encrypted) {
         s->crypt_method = crypt_method;
         memcpy(&s->aes_encrypt_key, &aes_encrypt_key, sizeof(aes_encrypt_key));
         memcpy(&s->aes_decrypt_key, &aes_decrypt_key, sizeof(aes_decrypt_key));
Signature · 1 line
2.1.0
Reviewed-by on v1 1/5
#2 lore raw

Re: [Qemu-devel] [PATCH 1/5] qcow2/qcow: protect against uninitialized encryption key

Quoted 12 lines · Daniel P. Berrange

When a qcow[2] file is opened, if the header reports an encryption method, this is used to set the 'crypt_method_header' field on the BDRVQcow[2]State struct, and the 'encrypted' flag in the BDRVState struct.

When doing I/O operations, the 'crypt_method' field on the BDRVQcow[2]State struct is checked to determine if encryption needs to be applied.

The crypt_method_header value is copied into crypt_method when the bdrv_set_key() method is called.

Quoted 8 lines

The QEMU code which opens a block device is expected to always do a check

   if (bdrv_is_encrypted(bs)) {
       bdrv_set_key(bs, ....key...);
   }

If code forgets todo this, then 'crypt_method' is never set

s/todo/to do/

Quoted 14 lines

and so when I/O is performed, QEMU writes plain text data into a sector which is expected to contain cipher text, or when reading, will return cipher text instead of plain text.

Change the qcow[2] code to consult bs->encrypted when deciding whether encryption is required, and assert(s->crypt_method) to protect against cases where the caller forgets to set the encryption key.

Also put an assert in the set_key methods to protect against the case where the caller sets an encryption key on a block device that does not have encryption

Quoted 7 lines
---
 block/qcow.c          | 10 +++++++---
 block/qcow2-cluster.c |  3 ++-
 block/qcow2.c         | 18 ++++++++++++------
 3 files changed, 21 insertions(+), 10 deletions(-)
Signature · 2 lines
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org
#3 lore raw

PATCH 2/5 util: move read_password method out of qemu-img into osdep/oslib

In reply to Daniel P. Berrange

The qemu-img.c file has a read_password() method impl that is used to prompt for passwords on the console, with impls for POSIX and Windows. This will be needed by qemu-io.c too, so move it into the QEMU osdep/oslib files where it can be shared without code duplication

---
 include/qemu/osdep.h |  2 ++
 qemu-img.c           | 93 +---------------------------------------------------
 util/oslib-posix.c   | 66 +++++++++++++++++++++++++++++++++++++
 util/oslib-win32.c   | 24 ++++++++++++++
 4 files changed, 93 insertions(+), 92 deletions(-)
include/qemu/osdep.h +2 -0
index b3300cc..3247364 100644
@@ -259,4 +259,6 @@ void qemu_set_tty_echo(int fd, bool echo);
 
 void os_mem_prealloc(int fd, char *area, size_t sz);
 
+int qemu_read_password(char *buf, int buf_size);
+
 #endif
qemu-img.c +1 -92

105 lines not on this page · raw message

util/oslib-posix.c +66 -0

75 lines not on this page · raw message

util/oslib-win32.c +24 -0
index 87cfbe0..730a670 100644
@@ -470,3 +470,27 @@ void os_mem_prealloc(int fd, char *area, size_t memory)
         memset(area + pagesize * i, 0, 1);
     }
 }
+
+
+/* XXX: put correct support for win32 */
+int qemu_read_password(char *buf, int buf_size)
+{
+    int c, i;
+
+    printf("Password: ");
+    fflush(stdout);
+    i = 0;
+    for (;;) {
+        c = getchar();
+        if (c < 0) {
+            buf[i] = '\0';
+            return -1;
+        } else if (c == '\n') {
+            break;
+        } else if (i < (buf_size - 1)) {
+            buf[i++] = c;
+        }
+    }
+    buf[i] = '\0';
+    return 0;
+}
Signature · 1 line
2.1.0
Reviewed-by on v1 2/5
#4 lore raw

Re: [Qemu-devel] [PATCH 2/5] util: move read_password method out of qemu-img into osdep/oslib

Quoted 19 lines · Daniel P. Berrange

The qemu-img.c file has a read_password() method impl that is used to prompt for passwords on the console, with impls for POSIX and Windows. This will be needed by qemu-io.c too, so move it into the QEMU osdep/oslib files where it can be shared without code duplication

---
 include/qemu/osdep.h |  2 ++
 qemu-img.c           | 93 +---------------------------------------------------
 util/oslib-posix.c   | 66 +++++++++++++++++++++++++++++++++++++
 util/oslib-win32.c   | 24 ++++++++++++++
 4 files changed, 93 insertions(+), 92 deletions(-)
include/qemu/osdep.h +0 -0
index b3300cc..3247364 100644

include/qemu/osdep.h void qemu_set_tty_echo(int fd, bool echo); · line 262

Quoted 4 lines
include/qemu/osdep.h +1 -0
@@ -259,4 +259,6 @@ void qemu_set_tty_echo(int fd, bool echo);
 
 void os_mem_prealloc(int fd, char *area, size_t sz);
 
+int qemu_read_password(char *buf, int buf_size);

Should we fix it to use size_t buf_size while at it? (or as a followup, to keep this one limited to code motion)

Signature · 2 lines
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org
#5 lore raw

PATCH 3/5 util: allow \n to terminate password input

In reply to Daniel P. Berrange

The qemu_read_password() method looks for \r to terminate the reading of the a password. This is what will be seen when reading the password from a TTY. When scripting though, it is useful to be able to send the password via a pipe, in which case we must look for \n to terminate password input.

---
 util/oslib-posix.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
util/oslib-posix.c +2 -1
index 1c23fd2..3ae4987 100644
@@ -467,7 +467,8 @@ int qemu_read_password(char *buf, int buf_size)
             ret = -1;
             break;
         } else {
-            if (ch == '\r') {
+            if (ch == '\r' ||
+                ch == '\n') {
                 ret = 0;
                 break;
             }
Signature · 1 line
2.1.0
Reviewed-by on v1 3/5
#6 lore raw

Re: [Qemu-devel] [PATCH 3/5] util: allow \n to terminate password input

Quoted 11 lines · Daniel P. Berrange

The qemu_read_password() method looks for \r to terminate the reading of the a password. This is what will be seen when reading the password from a TTY. When scripting though, it is useful to be able to send the password via a pipe, in which case we must look for \n to terminate password input.

---
 util/oslib-posix.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
Signature · 2 lines
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org
#7 lore raw

PATCH 4/5 qemu-io: prompt for encryption keys when required

In reply to Daniel P. Berrange

The qemu-io tool does not check if the image is encrypted so historically would silently corrupt the sectors by writing plain text data into them instead of cipher text. The earlier commit turns this mistake into a fatal abort, so check for encryption and prompt for key when required.

This enables us to add unit tests to ensure we don't break the ability of qemu-img to convert existing encrypted qcow2 files into a non-encrypted format.

---
 qemu-io.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
qemu-io.c +21 -0
index 8e41080..34ae933 100644
@@ -52,6 +52,7 @@ static const cmdinfo_t close_cmd = {
 static int openfile(char *name, int flags, QDict *opts)
 {
     Error *local_err = NULL;
+    BlockDriverState *bs;
 
     if (qemuio_blk) {
         fprintf(stderr, "file open already, try 'help close'\n");
@@ -68,7 +69,27 @@ static int openfile(char *name, int flags, QDict *opts)
         return 1;
     }
 
+    bs = blk_bs(qemuio_blk);
+    if (bdrv_is_encrypted(bs)) {
+        char password[256];
+        printf("Disk image '%s' is encrypted.\n", name);
+        if (qemu_read_password(password, sizeof(password)) < 0) {
+            error_report("No password given");
+            goto error;
+        }
+        if (bdrv_set_key(bs, password) < 0) {
+            error_report("invalid password");
+            goto error;
+        }
+    }
+
+
     return 0;
+
+ error:
+    blk_unref(qemuio_blk);
+    qemuio_blk = NULL;
+    return 1;
 }
 
 static void open_help(void)
Signature · 1 line
2.1.0
Reviewed-by on v1 4/5
#8 lore raw

Re: [Qemu-devel] [PATCH 4/5] qemu-io: prompt for encryption keys when required

Quoted 5 lines · Daniel P. Berrange

The qemu-io tool does not check if the image is encrypted so historically would silently corrupt the sectors by writing plain text data into them instead of cipher text. The earlier commit turns this mistake into a fatal abort, so check for encryption and prompt for key when required.

Doesn't that mean that 'git bisect' gives a crashing qemu-io for 3 patches? Should this be rearranged so that 1/5 comes after this to avoid triggering the abort?

Quoted 10 lines

This enables us to add unit tests to ensure we don't break the ability of qemu-img to convert existing encrypted qcow2 files into a non-encrypted format.

---
 qemu-io.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
Signature · 2 lines
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org
#9 lore raw

Re: [Qemu-devel] [PATCH 4/5] qemu-io: prompt for encryption keys when required

Quoted 10 lines · Eric Blake
Quoted 5 lines · Daniel P. Berrange

The qemu-io tool does not check if the image is encrypted so historically would silently corrupt the sectors by writing plain text data into them instead of cipher text. The earlier commit turns this mistake into a fatal abort, so check for encryption and prompt for key when required.

Doesn't that mean that 'git bisect' gives a crashing qemu-io for 3 patches? Should this be rearranged so that 1/5 comes after this to avoid triggering the abort?

I'm ambivalent on that - previously qemu-io was data corrupting for this scenario, so crashing isn't really that much worse :-)

It is easy enough to reorder these though if that's desired. The latter patches have no build time dep on the 1st patch, so its trivial for Kevin to re-order when applying if he thinks it is worth it.

Regards,
Daniel

Signature · 4 lines
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|
#10 lore raw

Re: [Qemu-devel] [PATCH 4/5] qemu-io: prompt for encryption keys when required

Quoted 8 lines · Daniel P. Berrange
Quoted 7 lines · Eric Blake
Quoted 5 lines · Daniel P. Berrange

The qemu-io tool does not check if the image is encrypted so historically would silently corrupt the sectors by writing plain text data into them instead of cipher text. The earlier commit turns this mistake into a fatal abort, so check for encryption and prompt for key when required.

Quoted 6 lines
Quoted 3 lines

Doesn't that mean that 'git bisect' gives a crashing qemu-io for 3 patches? Should this be rearranged so that 1/5 comes after this to avoid triggering the abort?

I'm ambivalent on that - previously qemu-io was data corrupting for this scenario, so crashing isn't really that much worse :-)

If it crashes before it can corrupt anything, I'd sell it as an improvement ;)

[...]

#11 lore raw

PATCH 5/5 tests: add test case for encrypted qcow2 read/write

In reply to Daniel P. Berrange

Add a simple test case for qemu-iotests that covers read/write with encrypted qcow2 files.

---
 tests/qemu-iotests/131     | 69 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/131.out | 46 +++++++++++++++++++++++++++++++
 tests/qemu-iotests/group   |  1 +
 3 files changed, 116 insertions(+)
 create mode 100755 tests/qemu-iotests/131
 create mode 100644 tests/qemu-iotests/131.out
tests/qemu-iotests/131 new file +69 -0
new file mode 100755
index 0000000..f44b0a0
@@ -0,0 +1,69 @@
+#!/bin/bash
+#
+# Test encrypted read/write using plain bdrv_read/bdrv_write
+#
+# Copyright (C) 2009 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
[email protected]
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+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=128M
+IMGOPTS="encryption=on" _make_test_img $size
+
+echo
+echo "== reading whole image =="
+echo "astrochicken" | $QEMU_IO -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== rewriting whole image =="
+echo "astrochicken" | $QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== verify pattern =="
+echo "astrochicken" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "== verify pattern failure with wrong password =="
+echo "platypus" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
+
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
tests/qemu-iotests/131.out new file +46 -0

46 lines not on this page · raw message

tests/qemu-iotests/group +1 -0
index 6ca3466..34b16cb 100644
@@ -128,3 +128,4 @@
 128 rw auto quick
 129 rw auto quick
 130 rw auto quick
+131 rw auto quick
Signature · 1 line
2.1.0
Reviewed-by on v1 5/5
#12 lore raw

Re: [Qemu-devel] [PATCH 5/5] tests: add test case for encrypted qcow2 read/write

Quoted 18 lines · Daniel P. Berrange

Add a simple test case for qemu-iotests that covers read/write with encrypted qcow2 files.

---
 tests/qemu-iotests/131     | 69 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/131.out | 46 +++++++++++++++++++++++++++++++
 tests/qemu-iotests/group   |  1 +
 3 files changed, 116 insertions(+)
 create mode 100755 tests/qemu-iotests/131
 create mode 100644 tests/qemu-iotests/131.out
tests/qemu-iotests/131 new file +0 -0
new file mode 100755
index 0000000..f44b0a0

tests/qemu-iotests/131 line 5

Quoted 5 lines
tests/qemu-iotests/131 new file +5 -0
@@ -0,0 +1,69 @@
+#!/bin/bash
+#
+# Test encrypted read/write using plain bdrv_read/bdrv_write
+#
+# Copyright (C) 2009 Red Hat, Inc.

Copy-and-paste strikes again; welcome to 2015. With that fixed,

Signature · 2 lines
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org
#13 lore raw

Re: [Qemu-devel] [Qemu-block] [PATCH 5/5] tests: add test case for encrypted qcow2 read/write

Quoted 12 lines · Eric Blake
Quoted 11 lines · Daniel P. Berrange

Add a simple test case for qemu-iotests that covers read/write with encrypted qcow2 files.

tests/qemu-iotests/131 | 69
++++++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/131.out | 46 +++++++++++++++++++++++++++++++
tests/qemu-iotests/group | 1 + 3 files changed, 116
insertions(+) create mode 100755 tests/qemu-iotests/131 create mode 100644 tests/qemu-iotests/131.out

Quoted 9 lines
Quoted 5 lines
tests/qemu-iotests/131 new renamed from tests/qemu-iotests/131 +0 -0

file mode 100755 index 0000000..f44b0a0 --- /dev/null +++ b/tests/qemu-iotests/131 @@ -0,0 +1,69 @@ +#!/bin/bash +# +# Test encrypted read/write using plain bdrv_read/bdrv_write +# +# Copyright (C) 2009 Red Hat, Inc.

Copy-and-paste strikes again; welcome to 2015. With that fixed,

Fam Zheng already has a patch on-list that uses test 131, and I think his patch was submitted first.

(Unless we want to play the "Who gets merged first?" game.)

--js

#14 lore raw

Re: [Qemu-devel] [Qemu-block] [PATCH 5/5] tests: add test case for encrypted qcow2 read/write

Quoted 9 lines · John Snow
Quoted 3 lines
Quoted 3 lines

tests/qemu-iotests/131 | 69
++++++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/131.out | 46 +++++++++++++++++++++++++++++++

Fam Zheng already has a patch on-list that uses test 131, and I think his patch was submitted first.

(Unless we want to play the "Who gets merged first?" game.)

That's the sort of conflict that I expect a maintainer can clean up, if there is no other reason for a respin (although it is not always easy to coax git into understanding that a patch would be valid if the file is renamed.

Signature · 2 lines
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org
#15 lore raw

Re: [Qemu-devel] [Qemu-block] [PATCH 5/5] tests: add test case for encrypted qcow2 read/write

Quoted 10 lines · Eric Blake
Quoted 9 lines · John Snow
Quoted 4 lines
Quoted 4 lines

tests/qemu-iotests/131 | 69
++++++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/131.out | 46
+++++++++++++++++++++++++++++++

Fam Zheng already has a patch on-list that uses test 131, and I think his patch was submitted first.

Quoted 7 lines
Quoted 1 line

(Unless we want to play the "Who gets merged first?" game.)

That's the sort of conflict that I expect a maintainer can clean up, if there is no other reason for a respin (although it is not always easy to coax git into understanding that a patch would be valid if the file is renamed.

Sure, whoever fixes it. Just pointing it out.

--js

Applied
#16 lore raw
In reply to Daniel P. Berrange

Am 12.05.2015 um 18:09 hat Daniel P. Berrange geschrieben:

Quoted 17 lines

I realize that qcow[2] encryption is a feature we have deprecated and will remove support for running it with the QEMU system emulators in this cycle. We do still need to make sure it continues to work for the sake of letting people run qemu-img convert to retrieve their data though.

Some of the other patches I'm working on which introduce a cypto cipher API touch this qcow2 code, thus I wanted to be able to test that it doesn't break anything.

I found that qemu-iotests didn't have any coverage of the qcow2 encryption code. For added fun, I then discovered that qemu-io doesn't check if an encryption key is required, so ends up writing plain text to the files instead of cipher, and returning cipher text for reads, instead of plain text. IOW qemu-io will corrupt encrypted qcow2 files on write.

Quoted 4 lines

This series adds some asserts that will protect against this kind of mistake, adds support for getting passwords to qemu-io (in the same manner that qemu-img supports), and finally adds a test case for reading/writing encrypted qcow2.

Thanks, applied to the block branch.

Kevin