render / rpms / libvirt

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