render / rpms / libvirt

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