mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 11:35:19 +00:00
qemu: caps: Format SEV platform data into qemuCaps cache
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@redhat.com> Acked-by: Peter Krempa <pkrempa@redhat.com> Tested-by: Brijesh Singh <brijesh.singh@amd.com>
This commit is contained in:
parent
764491c9dd
commit
77f51ab520
@ -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 virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
|
||||||
{
|
{
|
||||||
virQEMUCapsPtr ret = virQEMUCapsNew();
|
virQEMUCapsPtr ret = virQEMUCapsNew();
|
||||||
@ -1632,6 +1651,11 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
|
|||||||
for (i = 0; i < qemuCaps->ngicCapabilities; i++)
|
for (i = 0; i < qemuCaps->ngicCapabilities; i++)
|
||||||
ret->gicCapabilities[i] = qemuCaps->gicCapabilities[i];
|
ret->gicCapabilities[i] = qemuCaps->gicCapabilities[i];
|
||||||
|
|
||||||
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) &&
|
||||||
|
virQEMUCapsSEVInfoCopy(&ret->sevCapabilities,
|
||||||
|
qemuCaps->sevCapabilities) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
error:
|
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
|
* Parsing a doc that looks like
|
||||||
*
|
*
|
||||||
@ -3592,6 +3668,9 @@ virQEMUCapsLoadCache(virArch hostArch,
|
|||||||
}
|
}
|
||||||
VIR_FREE(nodes);
|
VIR_FREE(nodes);
|
||||||
|
|
||||||
|
if (virQEMUCapsParseSEVInfo(qemuCaps, ctxt) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM);
|
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM);
|
||||||
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU);
|
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 *
|
char *
|
||||||
virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
|
virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
|
||||||
{
|
{
|
||||||
@ -3790,6 +3887,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
|
|||||||
emulated ? "yes" : "no");
|
emulated ? "yes" : "no");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qemuCaps->sevCapabilities)
|
||||||
|
virQEMUCapsFormatSEVInfo(qemuCaps, &buf);
|
||||||
|
|
||||||
virBufferAdjustIndent(&buf, -2);
|
virBufferAdjustIndent(&buf, -2);
|
||||||
virBufferAddLit(&buf, "</qemuCaps>\n");
|
virBufferAddLit(&buf, "</qemuCaps>\n");
|
||||||
|
|
||||||
|
@ -142,6 +142,9 @@
|
|||||||
<gic supported='no'/>
|
<gic supported='no'/>
|
||||||
<vmcoreinfo supported='yes'/>
|
<vmcoreinfo supported='yes'/>
|
||||||
<genid supported='yes'/>
|
<genid supported='yes'/>
|
||||||
<sev supported='no'/>
|
<sev supported='yes'>
|
||||||
|
<cbitpos>47</cbitpos>
|
||||||
|
<reducedPhysBits>1</reducedPhysBits>
|
||||||
|
</sev>
|
||||||
</features>
|
</features>
|
||||||
</domainCapabilities>
|
</domainCapabilities>
|
||||||
|
@ -1253,4 +1253,10 @@
|
|||||||
<machine name='pc-0.11' hotplugCpus='yes' maxCpus='255'/>
|
<machine name='pc-0.11' hotplugCpus='yes' maxCpus='255'/>
|
||||||
<machine name='pc-0.12' hotplugCpus='yes' maxCpus='255'/>
|
<machine name='pc-0.12' hotplugCpus='yes' maxCpus='255'/>
|
||||||
<machine name='pc-0.10' 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>
|
</qemuCaps>
|
||||||
|
Loading…
Reference in New Issue
Block a user