[libvirt] [PATCH 16/18] tpm: Check TPM XML device configuration changes after edit

Stefan Berger stefanb at linux.vnet.ibm.com
Tue Jul 9 17:23:39 UTC 2019


Since swtpm does not support getting started once it was created
with encrypted enabled, we don't allow encryption to be removed.
Similarly, we do not allow encrypted to be added once swtpm has
run.

Signed-off-by: Stefan Berger <stefanb at linux.ibm.com>
---
 src/conf/domain_conf.c    | 56 +++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h    |  4 +++
 src/libvirt_private.syms  |  1 +
 src/qemu/qemu_driver.c    | 28 ++++++++++++++++++++
 src/qemu/qemu_extdevice.c |  2 +-
 src/qemu/qemu_extdevice.h |  3 +++
 6 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index df6238c299..68ffdcd4df 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31435,3 +31435,59 @@ virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics)
 
     return true;
 }
+
+
+static int
+virDomainCheckTPMChanges(virDomainDefPtr def,
+                         virDomainDefPtr newDef)
+{
+    bool oldEnc, newEnc;
+
+    if (!def->tpm)
+        return 0;
+
+    switch (def->tpm->type) {
+    case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+        if (virFileExists(def->tpm->data.emulator.storagepath)) {
+            /* VM has been started */
+            /* Once a VM was started with an encrypted state we allow
+             * less configuration changes.
+             */
+            oldEnc = def->tpm->data.emulator.encryption;
+            if (oldEnc && def->tpm->type != newDef->tpm->type) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("Changing the type of TPM is not allowed"));
+                return -1;
+            }
+            if (oldEnc && !newDef->tpm) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("Removing an encrypted TPM is not allowed"));
+                return -1;
+            }
+            newEnc = newDef->tpm->data.emulator.encryption;
+            if (oldEnc != newEnc) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                   _("TPM state encryption cannot be changed "
+                     "once VM was started"));
+                return -1;
+            }
+        }
+        break;
+    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+    case VIR_DOMAIN_TPM_TYPE_LAST:
+        break;
+    }
+
+    return 0;
+}
+
+
+int
+virDomainCheckDeviceChanges(virDomainDefPtr def,
+                            virDomainDefPtr newDef)
+{
+    if (!def || !newDef)
+        return 0;
+
+    return virDomainCheckTPMChanges(def, newDef);
+}
\ No newline at end of file
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a03986623a..a61faa7d57 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3623,3 +3623,7 @@ virDomainGraphicsGetRenderNode(const virDomainGraphicsDef *graphics);
 
 bool
 virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics);
+
+int
+virDomainCheckDeviceChanges(virDomainDefPtr def, virDomainDefPtr newDef)
+    ATTRIBUTE_NONNULL(2);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d693f7facb..f6f05ab207 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -205,6 +205,7 @@ virDomainBootTypeFromString;
 virDomainBootTypeToString;
 virDomainCapabilitiesPolicyTypeToString;
 virDomainCapsFeatureTypeToString;
+virDomainCheckDeviceChanges;
 virDomainChrConsoleTargetTypeFromString;
 virDomainChrConsoleTargetTypeToString;
 virDomainChrDefForeach;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ef2e980216..8f224582b6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -52,6 +52,7 @@
 #include "qemu_migration_params.h"
 #include "qemu_blockjob.h"
 #include "qemu_security.h"
+#include "qemu_extdevice.h"
 
 #include "virerror.h"
 #include "virlog.h"
@@ -7568,6 +7569,30 @@ qemuDomainCreate(virDomainPtr dom)
     return qemuDomainCreateWithFlags(dom, 0);
 }
 
+static int
+qemuDomainCheckDeviceChanges(virQEMUDriverPtr driver,
+                             virDomainDefPtr def)
+{
+    virDomainObjPtr vm;
+    int ret;
+
+    vm = virDomainObjListFindByUUID(driver->domains, def->uuid);
+    if (!vm)
+        return 0;
+
+    if (qemuExtDevicesInitPaths(driver, vm->def) < 0) {
+        ret = -1;
+        goto cleanup;
+    }
+
+    ret = virDomainCheckDeviceChanges(vm->def, def);
+
+ cleanup:
+    virDomainObjEndAPI(&vm);
+
+    return ret;
+}
+
 static virDomainPtr
 qemuDomainDefineXMLFlags(virConnectPtr conn,
                          const char *xml,
@@ -7604,6 +7629,9 @@ qemuDomainDefineXMLFlags(virConnectPtr conn,
     if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
         goto cleanup;
 
+    if (qemuDomainCheckDeviceChanges(driver, def) < 0)
+        goto cleanup;
+
     if (!(vm = virDomainObjListAdd(driver->domains, def,
                                    driver->xmlopt,
                                    0, &oldDef)))
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index a21caefaba..e576bca165 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -79,7 +79,7 @@ qemuExtDeviceLogCommand(qemuDomainLogContextPtr logCtxt,
  * stored and we can remove directories and files in case of domain XML
  * changes.
  */
-static int
+int
 qemuExtDevicesInitPaths(virQEMUDriverPtr driver,
                         virDomainDefPtr def)
 {
diff --git a/src/qemu/qemu_extdevice.h b/src/qemu/qemu_extdevice.h
index a72e05ce63..bbdb9a1cc2 100644
--- a/src/qemu/qemu_extdevice.h
+++ b/src/qemu/qemu_extdevice.h
@@ -53,3 +53,6 @@ bool qemuExtDevicesHasDevice(virDomainDefPtr def);
 int qemuExtDevicesSetupCgroup(virQEMUDriverPtr driver,
                               virDomainDefPtr def,
                               virCgroupPtr cgroup);
+
+int qemuExtDevicesInitPaths(virQEMUDriverPtr driver,
+                            virDomainDefPtr def);
-- 
2.20.1




More information about the libvir-list mailing list