]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
tpm: Check TPM XML device configuration changes after edit
authorStefan Berger <stefanb@linux.vnet.ibm.com>
Thu, 25 Jul 2019 18:22:13 +0000 (14:22 -0400)
committerDaniel P. Berrangé <berrange@redhat.com>
Fri, 26 Jul 2019 09:30:59 +0000 (10:30 +0100)
Since swtpm does not support getting started without password
once it was created with encryption enabled, we don't allow
encryption to be removed. Similarly, we do not allow encryption
to be added once swtpm has run. We also prevent chaning the type
of the TPM backend since the encrypted state is still around and
the next time one was to switch back to the emulator backend
and forgot the encryption the TPM would not work.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
src/qemu/qemu_driver.c
src/qemu/qemu_extdevice.c
src/qemu/qemu_extdevice.h

index 6673a323c6e0bc8cd5ab849d57020dceb7f841af..d60ef8106118ddd9ad8d027050505a0836bb55f2 100644 (file)
@@ -31430,3 +31430,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.hassecretuuid;
+            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.hassecretuuid;
+            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);
+}
index 8092893c2a0d2ab2c184796aa630c621eca11eea..285fa6c4961bdb41d37c1ac7135f6fa9c331ea38 100644 (file)
@@ -3636,3 +3636,7 @@ virDomainGraphicsGetRenderNode(const virDomainGraphicsDef *graphics);
 
 bool
 virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics);
+
+int
+virDomainCheckDeviceChanges(virDomainDefPtr def, virDomainDefPtr newDef)
+    ATTRIBUTE_NONNULL(2);
index a8d65e4318650a30907a1e6553608d76a2f6bae4..e1526031a5fc923157064129d86eac2ff691179c 100644 (file)
@@ -205,6 +205,7 @@ virDomainBootTypeFromString;
 virDomainBootTypeToString;
 virDomainCapabilitiesPolicyTypeToString;
 virDomainCapsFeatureTypeToString;
+virDomainCheckDeviceChanges;
 virDomainChrConsoleTargetTypeFromString;
 virDomainChrConsoleTargetTypeToString;
 virDomainChrDefForeach;
index e7720fbd998db2418e8474985cbdc2376e3bc270..9110d15cca23f11b8e8720042f8c54a3868ddd09 100644 (file)
@@ -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"
@@ -7600,6 +7601,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,
@@ -7636,6 +7661,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)))
index a21caefabae00e5d125fc8812ee3277bd968c852..e576bca165fe20e7858bf959df8caea50029766e 100644 (file)
@@ -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)
 {
index a72e05ce63c3ac0b5edb7a05b4166849fe16ab1d..bbdb9a1cc29f3a491613d6002ce4a50be8a287c8 100644 (file)
@@ -53,3 +53,6 @@ bool qemuExtDevicesHasDevice(virDomainDefPtr def);
 int qemuExtDevicesSetupCgroup(virQEMUDriverPtr driver,
                               virDomainDefPtr def,
                               virCgroupPtr cgroup);
+
+int qemuExtDevicesInitPaths(virQEMUDriverPtr driver,
+                            virDomainDefPtr def);