File libvirt-qemu-capabilities-force-update-if-the-microcode-version-does-not-match.patch of Package libvirt.11509
From 880bf81b173e53c53427a7b22ae577ecc0d48038 Mon Sep 17 00:00:00 2001
Message-Id: <880bf81b173e53c53427a7b22ae577ecc0d48038@dist-git>
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 12 Dec 2017 16:23:41 +0100
Subject: [PATCH] qemu: capabilities: force update if the microcode version
does not match
A microcode update can cause the CPUID bits to change; an example
from the past was the update that disabled TSX on several Haswell
and Broadwell machines.
Therefore, place microcode version in the virQEMUCaps struct and
XML, and rebuild the cache if the versions do not match.
CVE-2017-5715
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Conflicts:
src/qemu/qemu_capabilities.c
src/qemu/qemu_capabilities.h
- QEMU capabilities cache was refactored since 7.3
src/qemu/qemu_capspriv.h
- context; more functions were added since 7.3
tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml
- context; different package version in 7.3
tests/qemucapabilitiesdata/caps_2.10.0-gicv2.aarch64.xml
tests/qemucapabilitiesdata/caps_2.10.0-gicv3.aarch64.xml
tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml
tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml
tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
tests/qemucapabilitiesdata/caps_2.9.0.ppc64.xml
tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
- missing in 7.3
tests/qemucapabilitiestest.c
- no explicit TCG caps probing for KVM binaries in 7.3 yet
tests/qemucapsprobe.c
- the caps parameter for virQEMUCapsNewForBinaryInternal
added in 7.4 is missing in 7.3 (which matches 7.5 in this
respect)
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_capabilities.c | 57 ++++++++++++++++++++--
src/qemu/qemu_capspriv.h | 5 ++
tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml | 1 +
.../caps_2.6.0-gicv2.aarch64.xml | 1 +
.../caps_2.6.0-gicv3.aarch64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 1 +
tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 1 +
tests/qemucapabilitiestest.c | 8 +++
tests/qemucapsprobe.c | 2 +-
18 files changed, 80 insertions(+), 6 deletions(-)
Index: libvirt-2.0.0/src/qemu/qemu_capabilities.c
===================================================================
--- libvirt-2.0.0.orig/src/qemu/qemu_capabilities.c
+++ libvirt-2.0.0/src/qemu/qemu_capabilities.c
@@ -359,6 +359,7 @@ struct _virQEMUCaps {
unsigned int version;
unsigned int kvmVersion;
+ unsigned int microcodeVersion;
char *package;
virArch arch;
@@ -2035,6 +2036,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEM
ret->usedQMP = qemuCaps->usedQMP;
ret->version = qemuCaps->version;
ret->kvmVersion = qemuCaps->kvmVersion;
+ ret->microcodeVersion = qemuCaps->microcodeVersion;
if (VIR_STRDUP(ret->package, qemuCaps->package) < 0)
goto error;
@@ -2882,6 +2884,13 @@ virQEMUCapsLoadCache(virQEMUCapsPtr qemu
goto cleanup;
}
+ if (virXPathUInt("string(./microcodeVersion)", ctxt,
+ &qemuCaps->microcodeVersion) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing microcode version in QEMU capabilities cache"));
+ goto cleanup;
+ }
+
/* Don't check for NULL, since it is optional and thus may be missing */
qemuCaps->package = virXPathString("string(./package)", ctxt);
@@ -3065,6 +3074,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qe
virBufferAsprintf(&buf, "<kvmVersion>%d</kvmVersion>\n",
qemuCaps->kvmVersion);
+ virBufferAsprintf(&buf, "<microcodeVersion>%u</microcodeVersion>\n",
+ qemuCaps->microcodeVersion);
+
if (qemuCaps->package)
virBufferAsprintf(&buf, "<package>%s</package>\n",
qemuCaps->package);
@@ -3211,7 +3223,8 @@ virQEMUCapsReset(virQEMUCapsPtr qemuCaps
static int
virQEMUCapsInitCached(virQEMUCapsPtr qemuCaps,
- const char *cacheDir)
+ const char *cacheDir,
+ unsigned int microcodeVersion)
{
char *capsdir = NULL;
char *capsfile = NULL;
@@ -3263,6 +3276,20 @@ virQEMUCapsInitCached(virQEMUCapsPtr qem
goto cleanup;
}
+ if ((virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM) ||
+ virQEMUCapsGet(qemuCaps, QEMU_CAPS_ENABLE_KVM)) &&
+ microcodeVersion != qemuCaps->microcodeVersion) {
+ VIR_DEBUG("Outdated capabilities for '%s': microcode version changed "
+ "(%u vs %u)",
+ qemuCaps->binary,
+ microcodeVersion,
+ qemuCaps->microcodeVersion);
+ ignore_value(unlink(capsfile));
+ virQEMUCapsReset(qemuCaps);
+ ret = 0;
+ goto cleanup;
+ }
+
/* Discard cache if QEMU binary or libvirtd changed */
if (qemuctime != qemuCaps->ctime ||
selfctime != virGetSelfLastChanged() ||
@@ -3739,6 +3766,7 @@ virQEMUCapsNewForBinaryInternal(const ch
const char *cacheDir,
uid_t runUid,
gid_t runGid,
+ unsigned int microcodeVersion,
bool qmpOnly)
{
virQEMUCapsPtr qemuCaps;
@@ -3773,7 +3801,7 @@ virQEMUCapsNewForBinaryInternal(const ch
if (!cacheDir)
rv = 0;
- else if ((rv = virQEMUCapsInitCached(qemuCaps, cacheDir)) < 0)
+ else if ((rv = virQEMUCapsInitCached(qemuCaps, cacheDir, microcodeVersion)) < 0)
goto error;
if (rv == 0) {
@@ -3796,6 +3824,10 @@ virQEMUCapsNewForBinaryInternal(const ch
goto error;
}
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM) ||
+ virQEMUCapsGet(qemuCaps, QEMU_CAPS_ENABLE_KVM))
+ qemuCaps->microcodeVersion = microcodeVersion;
+
if (cacheDir &&
virQEMUCapsRememberCached(qemuCaps, cacheDir) < 0)
goto error;
@@ -3816,10 +3848,12 @@ virQEMUCapsNewForBinary(const char *bina
const char *libDir,
const char *cacheDir,
uid_t runUid,
- gid_t runGid)
+ gid_t runGid,
+ unsigned int microcodeVersion)
{
return virQEMUCapsNewForBinaryInternal(binary, libDir, cacheDir,
- runUid, runGid, false);
+ runUid, runGid,
+ microcodeVersion, false);
}
@@ -3881,6 +3915,9 @@ virQEMUCapsCacheNew(const char *libDir,
{
virQEMUCapsCachePtr cache;
+ if (virQEMUCapsInitialize() < 0)
+ return NULL;
+
if (VIR_ALLOC(cache) < 0)
return NULL;
@@ -3900,6 +3937,7 @@ virQEMUCapsCacheNew(const char *libDir,
cache->runUid = runUid;
cache->runGid = runGid;
+ cache->microcodeVersion = cpuMicrocodeVersion;
return cache;
@@ -3933,7 +3971,8 @@ virQEMUCapsCacheLookup(virQEMUCapsCacheP
binary);
ret = virQEMUCapsNewForBinary(binary, cache->libDir,
cache->cacheDir,
- cache->runUid, cache->runGid);
+ cache->runUid, cache->runGid,
+ cache->microcodeVersion);
if (ret) {
VIR_DEBUG("Caching capabilities %p for %s",
ret, binary);
@@ -4375,3 +4414,11 @@ virQEMUCapsFillDomainCaps(virDomainCapsP
return -1;
return 0;
}
+
+
+void
+virQEMUCapsSetMicrocodeVersion(virQEMUCapsPtr qemuCaps,
+ unsigned int microcodeVersion)
+{
+ qemuCaps->microcodeVersion = microcodeVersion;
+}
Index: libvirt-2.0.0/src/qemu/qemu_capspriv.h
===================================================================
--- libvirt-2.0.0.orig/src/qemu/qemu_capspriv.h
+++ libvirt-2.0.0/src/qemu/qemu_capspriv.h
@@ -35,6 +35,7 @@ struct _virQEMUCapsCache {
char *cacheDir;
uid_t runUid;
gid_t runGid;
+ unsigned int microcodeVersion;
};
virQEMUCapsPtr
@@ -43,6 +44,7 @@ virQEMUCapsNewForBinaryInternal(const ch
const char *cacheDir,
uid_t runUid,
gid_t runGid,
+ unsigned int microcodeVersion,
bool qmpOnly);
int virQEMUCapsLoadCache(virQEMUCapsPtr qemuCaps,
@@ -54,4 +56,7 @@ char *virQEMUCapsFormatCache(virQEMUCaps
time_t selfCTime,
unsigned long selfVersion);
+void
+virQEMUCapsSetMicrocodeVersion(virQEMUCapsPtr qemuCaps,
+ unsigned int microcodeVersion);
#endif
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
@@ -116,6 +116,7 @@
<flag name='device-tray-moved-event'/>
<version>1002002</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>26869</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='qemu64'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
@@ -134,6 +134,7 @@
<flag name='nec-usb-xhci-ports'/>
<version>1003001</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>30151</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='qemu64'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
@@ -135,6 +135,7 @@
<flag name='nec-usb-xhci-ports'/>
<version>1004002</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>30868</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='Opteron_G5'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
@@ -145,6 +145,7 @@
<flag name='nec-usb-xhci-ports'/>
<version>1005003</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>46972</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='Opteron_G5'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
@@ -150,6 +150,7 @@
<flag name='nec-usb-xhci-ports'/>
<version>1006000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>45201</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='Opteron_G5'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
@@ -152,6 +152,7 @@
<flag name='nec-usb-xhci-ports'/>
<version>1007000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>50645</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='Opteron_G5'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
@@ -167,6 +167,7 @@
<flag name='drive-detect-zeroes'/>
<version>2001001</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>59399</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='Opteron_G5'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml
@@ -184,6 +184,7 @@
<flag name='drive-detect-zeroes'/>
<version>2004000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>75168</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='Opteron_G5'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
@@ -189,6 +189,7 @@
<flag name='tls-creds-x509'/>
<version>2005000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>79203</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='Opteron_G5'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
@@ -159,6 +159,7 @@
<flag name='tls-creds-x509'/>
<version>2005094</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>81580</microcodeVersion>
<package></package>
<arch>aarch64</arch>
<cpu name='pxa262'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
@@ -159,6 +159,7 @@
<flag name='tls-creds-x509'/>
<version>2005094</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>81580</microcodeVersion>
<package></package>
<arch>aarch64</arch>
<cpu name='pxa262'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml
@@ -153,6 +153,7 @@
<flag name='tls-creds-x509'/>
<version>2005094</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>100397</microcodeVersion>
<package></package>
<arch>ppc64</arch>
<cpu name='default'/>
Index: libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
+++ libvirt-2.0.0/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
@@ -195,6 +195,7 @@
<flag name='tls-creds-x509'/>
<version>2006000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>81329</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu name='Opteron_G5'/>
Index: libvirt-2.0.0/tests/qemucapabilitiestest.c
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapabilitiestest.c
+++ libvirt-2.0.0/tests/qemucapabilitiestest.c
@@ -61,6 +61,14 @@ testQemuCaps(const void *opaque)
qemuMonitorTestGetMonitor(mon)) < 0)
goto cleanup;
+ if (virQEMUCapsGet(capsActual, QEMU_CAPS_KVM) ||
+ virQEMUCapsGet(capsActual, QEMU_CAPS_ENABLE_KVM)) {
+ /* Fill microcodeVersion with a "random" value which is the file
+ * length to provide a reproducible number for testing.
+ */
+ virQEMUCapsSetMicrocodeVersion(capsActual, virFileLength(repliesFile, -1));
+ }
+
if (!(actual = virQEMUCapsFormatCache(capsActual, 0, 0)))
goto cleanup;
Index: libvirt-2.0.0/tests/qemucapsprobe.c
===================================================================
--- libvirt-2.0.0.orig/tests/qemucapsprobe.c
+++ libvirt-2.0.0/tests/qemucapsprobe.c
@@ -71,7 +71,7 @@ main(int argc, char **argv)
return EXIT_FAILURE;
if (!(caps = virQEMUCapsNewForBinaryInternal(argv[1], "/tmp", NULL,
- -1, -1, true)))
+ -1, -1, 0, true)))
return EXIT_FAILURE;
virObjectUnref(caps);