From: Peter Krempa <[email protected]>

The image metadata crawler code generally forbids qcow2 images which
have a 'backing_file' but don't specify a 'backing_file_fmt' header as
we don't want to probe the format due to security implications.

There's one notable exception for the last image in the chain which can
be format probed if it doesn't have another 'backing_file'.

As the comment in 'virStorageSourceGetMetadataRecurse' suggests we don't
want to allow the probe if anything probed would influence access to
more resources. Unfortunately that didn't involve 'data_file' header
which gives more access.

Fortunately there is no way for a guest OS having a 'raw' disk and
access to libvirt's snapshot API to abuse this as libvirt's snapshot API
does specify the header. Other cases where an arbitrary image is passed
to libvirt can 'backing_file'+'backing_file_fmt' directly to access
arbitrary file on disk so this bug is no worse in this regard.

Nevertheless it's a bug which should be fixed.

Closes: https://gitlab.com/libvirt/libvirt/-/work_items/904
Fixes: 0a3d177d9bd6cc608cc8e5769188e5f45f70ee62
Signed-off-by: Peter Krempa <[email protected]>
---
 src/storage_file/storage_source.c             |  3 +-
 tests/virstoragetest.c                        |  2 +-
 .../qcow2datafile-qcow2_qcow2-datafile-auto   | 31 -------------------
 3 files changed, 3 insertions(+), 33 deletions(-)
 delete mode 100644 
tests/virstoragetestdata/out/qcow2datafile-qcow2_qcow2-datafile-auto

diff --git a/src/storage_file/storage_source.c 
b/src/storage_file/storage_source.c
index e886433bb4..aa7e834819 100644
--- a/src/storage_file/storage_source.c
+++ b/src/storage_file/storage_source.c
@@ -1426,9 +1426,10 @@ virStorageSourceGetMetadataRecurse(virStorageSource *src,
     /* If we probed the format we MUST ensure that nothing else than the 
current
      * image is considered for security labelling and/or recursion. */
     if (orig_format == VIR_STORAGE_FILE_AUTO) {
-        if (src->backingStoreRaw) {
+        if (src->backingStoreRaw || src->dataFileRaw) {
             src->format = VIR_STORAGE_FILE_RAW;
             VIR_FREE(src->backingStoreRaw);
+            VIR_FREE(src->dataFileRaw);
             return -2;
         }
     }
diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c
index 1514991c20..4c9272150c 100644
--- a/tests/virstoragetest.c
+++ b/tests/virstoragetest.c
@@ -499,7 +499,7 @@ mymain(void)
                VIR_STORAGE_FILE_QCOW2, EXP_PASS);
     TEST_CHAIN("qcow2datafile-qcow2_qcow2-datafile-auto",
                abs_srcdir 
"/virstoragetestdata/images/qcow2_datafile-auto.qcow2",
-               VIR_STORAGE_FILE_QCOW2, EXP_PASS);
+               VIR_STORAGE_FILE_QCOW2, EXP_FAIL);

     /* broken qcow2 with a 'data_file' which is an empty string */
     TEST_CHAIN("qcow2-datafile-broken",
diff --git 
a/tests/virstoragetestdata/out/qcow2datafile-qcow2_qcow2-datafile-auto 
b/tests/virstoragetestdata/out/qcow2datafile-qcow2_qcow2-datafile-auto
deleted file mode 100644
index 421e0c8d5a..0000000000
--- a/tests/virstoragetestdata/out/qcow2datafile-qcow2_qcow2-datafile-auto
+++ /dev/null
@@ -1,31 +0,0 @@
-path:ABS_SRCDIR/virstoragetestdata/images/qcow2_datafile-auto.qcow2
-backingStoreRaw: datafile.qcow2
-backingStoreRawFormat: <null>(-1)
-dataFileRaw: <null>
-capacity: 1024
-encryption: 0
-relPath:<null>
-type:file
-format:qcow2
-protocol:none
-hostname:<null>
-
-path:ABS_SRCDIR/virstoragetestdata/images/datafile.qcow2
-backingStoreRaw: <null>
-backingStoreRawFormat: none(0)
-dataFileRaw: raw
-capacity: 1024
-encryption: 0
-relPath:datafile.qcow2
-type:file
-format:qcow2
-protocol:none
-hostname:<null>
-
- dataFileStoreSource for 'ABS_SRCDIR/virstoragetestdata/images/datafile.qcow2':
-  path: ABS_SRCDIR/virstoragetestdata/images/raw
-  capacity: 0
-  encryption: 0
-  type:file
-  format:raw
-
-- 
2.55.0

Reply via email to