Blame SOURCES/libvirt-virStorageFileGetMetadataRecurse-Allow-format-probing-under-special-circumstances.patch

fbe740
From 1e3921f1065972dc236bc726f19be37492a145c6 Mon Sep 17 00:00:00 2001
fbe740
Message-Id: <1e3921f1065972dc236bc726f19be37492a145c6@dist-git>
fbe740
From: Peter Krempa <pkrempa@redhat.com>
fbe740
Date: Fri, 28 Feb 2020 10:24:43 +0100
fbe740
Subject: [PATCH] virStorageFileGetMetadataRecurse: Allow format probing under
fbe740
 special circumstances
fbe740
MIME-Version: 1.0
fbe740
Content-Type: text/plain; charset=UTF-8
fbe740
Content-Transfer-Encoding: 8bit
fbe740
fbe740
Allow format probing to work around lazy clients which did not specify
fbe740
their format in the overlay. Format probing will be allowed only, if we
fbe740
are able to probe the image, the probing result was successful and the
fbe740
probed image does not have any backing or data file.
fbe740
fbe740
This relaxes the restrictions which were imposed in commit 3615e8b39bad
fbe740
in cases when we know that the image probing will not result in security
fbe740
issues or data corruption.
fbe740
fbe740
We perform the image format detection and in the case that we were able
fbe740
to probe the format and the format does not specify a backing store (or
fbe740
doesn't support backing store) we can use this format.
fbe740
fbe740
With pre-blockdev configurations this will restore the previous
fbe740
behaviour for the images mentioned above as qemu would probe the format
fbe740
anyways. It also improves error reporting compared to the old state as
fbe740
we now report that the backing chain will be broken in case when there
fbe740
is a backing file.
fbe740
fbe740
In blockdev configurations this ensures that libvirt will not cause data
fbe740
corruption by ending the chain prematurely without notifying the user,
fbe740
but still allows the old semantics when the users forgot to specify the
fbe740
format.
fbe740
fbe740
Users thus don't have to re-invent when image format detection is safe
fbe740
to do.
fbe740
fbe740
The price for this is that libvirt will need to keep the image format
fbe740
detector still current and working or replace it by invocation of
fbe740
qemu-img.
fbe740
fbe740
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
fbe740
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
fbe740
(cherry picked from commit ae9e6c2a2b75d958995c661f7bb64ed4353a6404)
fbe740
fbe740
https://bugzilla.redhat.com/show_bug.cgi?id=1798148
fbe740
Message-Id: <77d1d21a0ce64fd49c501b1ed3667307cbab0b73.1582881363.git.pkrempa@redhat.com>
fbe740
Reviewed-by: Ján Tomko <jtomko@redhat.com>
fbe740
---
fbe740
 src/util/virstoragefile.c | 52 ++++++++++++++++++++++-----------------
fbe740
 1 file changed, 30 insertions(+), 22 deletions(-)
fbe740
fbe740
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
fbe740
index 0bfd9e16e9..b88763b267 100644
fbe740
--- a/src/util/virstoragefile.c
fbe740
+++ b/src/util/virstoragefile.c
fbe740
@@ -4986,6 +4986,7 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
fbe740
                                  virHashTablePtr cycle,
fbe740
                                  unsigned int depth)
fbe740
 {
fbe740
+    virStorageFileFormat orig_format = src->format;
fbe740
     size_t headerLen;
fbe740
     int rv;
fbe740
     g_autofree char *buf = NULL;
fbe740
@@ -4995,10 +4996,17 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
fbe740
               NULLSTR(src->path), src->format,
fbe740
               (unsigned int)uid, (unsigned int)gid);
fbe740
 
fbe740
+    if (src->format == VIR_STORAGE_FILE_AUTO_SAFE)
fbe740
+        src->format = VIR_STORAGE_FILE_AUTO;
fbe740
+
fbe740
     /* exit if we can't load information about the current image */
fbe740
     rv = virStorageFileSupportsBackingChainTraversal(src);
fbe740
-    if (rv <= 0)
fbe740
+    if (rv <= 0) {
fbe740
+        if (orig_format == VIR_STORAGE_FILE_AUTO)
fbe740
+            return -2;
fbe740
+
fbe740
         return rv;
fbe740
+    }
fbe740
 
fbe740
     if (virStorageFileGetMetadataRecurseReadHeader(src, parent, uid, gid,
fbe740
                                                    &buf, &headerLen, cycle) < 0)
fbe740
@@ -5007,6 +5015,18 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
fbe740
     if (virStorageFileGetMetadataInternal(src, buf, headerLen) < 0)
fbe740
         return -1;
fbe740
 
fbe740
+    /* If we probed the format we MUST ensure that nothing else than the current
fbe740
+     * image (this includes both backing files and external data store) is
fbe740
+     * considered for security labelling and/or recursion. */
fbe740
+    if (orig_format == VIR_STORAGE_FILE_AUTO) {
fbe740
+        if (src->backingStoreRaw || src->externalDataStoreRaw) {
fbe740
+            src->format = VIR_STORAGE_FILE_RAW;
fbe740
+            VIR_FREE(src->backingStoreRaw);
fbe740
+            VIR_FREE(src->externalDataStoreRaw);
fbe740
+            return -2;
fbe740
+        }
fbe740
+    }
fbe740
+
fbe740
     if (src->backingStoreRaw) {
fbe740
         if ((rv = virStorageSourceNewFromBacking(src, &backingStore)) < 0)
fbe740
             return -1;
fbe740
@@ -5015,33 +5035,21 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
fbe740
         if (rv == 1)
fbe740
             return 0;
fbe740
 
fbe740
-        if (backingStore->format == VIR_STORAGE_FILE_AUTO) {
fbe740
-            /* Assuming the backing store to be raw can lead to failures. We do
fbe740
-             * it only when we must not report an error to prevent losing VMs.
fbe740
-             * Otherwise report an error.
fbe740
-             */
fbe740
-            if (report_broken) {
fbe740
+        if ((rv = virStorageFileGetMetadataRecurse(backingStore, parent,
fbe740
+                                                   uid, gid,
fbe740
+                                                   report_broken,
fbe740
+                                                   cycle, depth + 1)) < 0) {
fbe740
+            if (!report_broken)
fbe740
+                return 0;
fbe740
+
fbe740
+            if (rv == -2) {
fbe740
                 virReportError(VIR_ERR_OPERATION_INVALID,
fbe740
                                _("format of backing image '%s' of image '%s' was not specified in the image metadata "
fbe740
                                  "(See https://libvirt.org/kbase/backing_chains.html for troubleshooting)"),
fbe740
                                src->backingStoreRaw, NULLSTR(src->path));
fbe740
-                return -1;
fbe740
             }
fbe740
 
fbe740
-            backingStore->format = VIR_STORAGE_FILE_RAW;
fbe740
-        }
fbe740
-
fbe740
-        if (backingStore->format == VIR_STORAGE_FILE_AUTO_SAFE)
fbe740
-            backingStore->format = VIR_STORAGE_FILE_AUTO;
fbe740
-
fbe740
-        if (virStorageFileGetMetadataRecurse(backingStore, parent,
fbe740
-                                             uid, gid,
fbe740
-                                             report_broken,
fbe740
-                                             cycle, depth + 1) < 0) {
fbe740
-            if (report_broken)
fbe740
-                return -1;
fbe740
-            else
fbe740
-                return 0;
fbe740
+            return -1;
fbe740
         }
fbe740
 
fbe740
         backingStore->id = depth;
fbe740
-- 
fbe740
2.25.1
fbe740