[libvirt] [PATCH v2 4/4] qemu: caps: Format SEV platform data into qemuCaps cache

Erik Skultety eskultet at redhat.com
Thu Aug 16 10:35:18 UTC 2018


Since we're not saving the platform-specific data into a cache, we're
not going to populate the structure, which in turn will cause a crash
upon calling virNodeGetSEVInfo because of a NULL pointer dereference.
Ultimately, we should start caching this data along with host-specific
capabilities like NUMA and SELinux stuff into a separate cache, but for
the time being, this is a semi-proper fix for a potential crash.

Backtrace (requires libvirtd restart to load qemu caps from cache):
    #0 qemuGetSEVInfoToParams
    #1 qemuNodeGetSEVInfo
    #2 virNodeGetSEVInfo
    #3 remoteDispatchNodeGetSevInfo
    #4 remoteDispatchNodeGetSevInfoHelper
    #5 virNetServerProgramDispatchCall
    #6 virNetServerProgramDispatch
    #7 virNetServerProcessMsg
    #8 virNetServerHandleJob
    #9 virThreadPoolWorker
    #10 virThreadHelper

https: //bugzilla.redhat.com/show_bug.cgi?id=1612009
Signed-off-by: Erik Skultety <eskultet at redhat.com>
Acked-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_capabilities.c                      | 100 ++++++++++++++++++++++
 tests/domaincapsschemadata/qemu_2.12.0.x86_64.xml |   5 +-
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml |   6 ++
 3 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index fc46a380f6..9edb4ca4d4 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -1570,6 +1570,25 @@ virQEMUCapsHostCPUDataClear(virQEMUCapsHostCPUDataPtr cpuData)
 }


+static int
+virQEMUCapsSEVInfoCopy(virSEVCapabilityPtr *dst,
+                       virSEVCapabilityPtr src)
+{
+    VIR_AUTOPTR(virSEVCapability) tmp = NULL;
+
+    if (VIR_ALLOC(tmp) < 0 ||
+        VIR_STRDUP(tmp->pdh, src->pdh) < 0 ||
+        VIR_STRDUP(tmp->cert_chain, src->cert_chain) < 0)
+        return -1;
+
+    tmp->cbitpos = src->cbitpos;
+    tmp->reduced_phys_bits = src->reduced_phys_bits;
+
+    VIR_STEAL_PTR(*dst, tmp);
+    return 0;
+}
+
+
 virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
 {
     virQEMUCapsPtr ret = virQEMUCapsNew();
@@ -1632,6 +1651,11 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
     for (i = 0; i < qemuCaps->ngicCapabilities; i++)
         ret->gicCapabilities[i] = qemuCaps->gicCapabilities[i];

+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) &&
+        virQEMUCapsSEVInfoCopy(&ret->sevCapabilities,
+                               qemuCaps->sevCapabilities) < 0)
+        goto error;
+
     return ret;

  error:
@@ -3344,6 +3368,58 @@ virQEMUCapsCachePrivFree(void *privData)
 }


+static int
+virQEMUCapsParseSEVInfo(virQEMUCapsPtr qemuCaps, xmlXPathContextPtr ctxt)
+{
+    VIR_AUTOPTR(virSEVCapability) sev = NULL;
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST))
+        return 0;
+
+    if (virXPathBoolean("boolean(./sev)", ctxt) == 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing SEV platform data in QEMU "
+                         "capabilities cache"));
+        return -1;
+    }
+
+    if (VIR_ALLOC(sev) < 0)
+        return -1;
+
+    if (virXPathUInt("string(./sev/cbitpos)", ctxt, &sev->cbitpos) < 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing or malformed SEV cbitpos information "
+                         "in QEMU capabilities cache"));
+        return -1;
+    }
+
+    if (virXPathUInt("string(./sev/reducedPhysBits)", ctxt,
+                     &sev->reduced_phys_bits) < 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing or malformed SEV reducedPhysBits information "
+                         "in QEMU capabilities cache"));
+        return -1;
+    }
+
+    if (!(sev->pdh = virXPathString("string(./sev/pdh)", ctxt)))  {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing SEV pdh information "
+                         "in QEMU capabilities cache"));
+        return -1;
+    }
+
+    if (!(sev->cert_chain = virXPathString("string(./sev/certChain)", ctxt))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing SEV certChain information "
+                         "in QEMU capabilities cache"));
+        return -1;
+    }
+
+    VIR_STEAL_PTR(qemuCaps->sevCapabilities, sev);
+    return 0;
+}
+
+
 /*
  * Parsing a doc that looks like
  *
@@ -3592,6 +3668,9 @@ virQEMUCapsLoadCache(virArch hostArch,
     }
     VIR_FREE(nodes);

+    if (virQEMUCapsParseSEVInfo(qemuCaps, ctxt) < 0)
+        goto cleanup;
+
     virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM);
     virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU);

@@ -3709,6 +3788,24 @@ virQEMUCapsFormatCPUModels(virQEMUCapsPtr qemuCaps,
 }


+static void
+virQEMUCapsFormatSEVInfo(virQEMUCapsPtr qemuCaps, virBufferPtr buf)
+{
+    virSEVCapabilityPtr sev = virQEMUCapsGetSEVCapabilities(qemuCaps);
+
+    virBufferAddLit(buf, "<sev>\n");
+    virBufferAdjustIndent(buf, 2);
+    virBufferAsprintf(buf, "<cbitpos>%u</cbitpos>\n", sev->cbitpos);
+    virBufferAsprintf(buf, "<reducedPhysBits>%u</reducedPhysBits>\n",
+                      sev->reduced_phys_bits);
+    virBufferEscapeString(buf, "<pdh>%s</pdh>\n", sev->pdh);
+    virBufferEscapeString(buf, "<certChain>%s</certChain>\n",
+                          sev->cert_chain);
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</sev>\n");
+}
+
+
 char *
 virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
 {
@@ -3790,6 +3887,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
                           emulated ? "yes" : "no");
     }

+    if (qemuCaps->sevCapabilities)
+        virQEMUCapsFormatSEVInfo(qemuCaps, &buf);
+
     virBufferAdjustIndent(&buf, -2);
     virBufferAddLit(&buf, "</qemuCaps>\n");

diff --git a/tests/domaincapsschemadata/qemu_2.12.0.x86_64.xml b/tests/domaincapsschemadata/qemu_2.12.0.x86_64.xml
index 7a1be4c093..a8d6a4d629 100644
--- a/tests/domaincapsschemadata/qemu_2.12.0.x86_64.xml
+++ b/tests/domaincapsschemadata/qemu_2.12.0.x86_64.xml
@@ -142,6 +142,9 @@
     <gic supported='no'/>
     <vmcoreinfo supported='yes'/>
     <genid supported='yes'/>
-    <sev supported='no'/>
+    <sev supported='yes'>
+      <cbitpos>47</cbitpos>
+      <reducedPhysBits>1</reducedPhysBits>
+    </sev>
   </features>
 </domainCapabilities>
diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
index d34d762ca8..d134e5632d 100644
--- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
@@ -1253,4 +1253,10 @@
   <machine name='pc-0.11' hotplugCpus='yes' maxCpus='255'/>
   <machine name='pc-0.12' hotplugCpus='yes' maxCpus='255'/>
   <machine name='pc-0.10' hotplugCpus='yes' maxCpus='255'/>
+  <sev>
+    <cbitpos>47</cbitpos>
+    <reducedPhysBits>1</reducedPhysBits>
+    <pdh>AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA</pdh>
+    <certChain>AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA</certChain>
+  </sev>
 </qemuCaps>
--
2.14.4




More information about the libvir-list mailing list