c1c534
From ac8540f237280b2e302949f15d229e13477245c7 Mon Sep 17 00:00:00 2001
c1c534
Message-Id: <ac8540f237280b2e302949f15d229e13477245c7@dist-git>
c1c534
From: Paolo Bonzini <pbonzini@redhat.com>
c1c534
Date: Tue, 12 Dec 2017 16:23:41 +0100
c1c534
Subject: [PATCH] util: introduce virHostCPUGetMicrocodeVersion
c1c534
c1c534
This new API reads host's CPU microcode version from /proc/cpuinfo.
c1c534
c1c534
Unfortunately, there is no other way of reading microcode version which
c1c534
would be usable from both system and session daemon.
c1c534
c1c534
CVE-2017-5715
c1c534
c1c534
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
c1c534
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c1c534
---
c1c534
 src/libvirt_private.syms |  1 +
c1c534
 src/util/virhostcpu.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
c1c534
 src/util/virhostcpu.h    |  2 ++
c1c534
 3 files changed, 46 insertions(+)
c1c534
c1c534
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
c1c534
index 85b15314a9..57999e77b0 100644
c1c534
--- a/src/libvirt_private.syms
c1c534
+++ b/src/libvirt_private.syms
c1c534
@@ -1861,6 +1861,7 @@ virHostCPUGetCount;
c1c534
 virHostCPUGetInfo;
c1c534
 virHostCPUGetKVMMaxVCPUs;
c1c534
 virHostCPUGetMap;
c1c534
+virHostCPUGetMicrocodeVersion;
c1c534
 virHostCPUGetOnline;
c1c534
 virHostCPUGetOnlineBitmap;
c1c534
 virHostCPUGetPresentBitmap;
c1c534
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
c1c534
index bd58aa43df..a7ae7cd4cb 100644
c1c534
--- a/src/util/virhostcpu.c
c1c534
+++ b/src/util/virhostcpu.c
c1c534
@@ -1211,3 +1211,46 @@ virHostCPUGetKVMMaxVCPUs(void)
c1c534
     return -1;
c1c534
 }
c1c534
 #endif /* HAVE_LINUX_KVM_H */
c1c534
+
c1c534
+
c1c534
+#ifdef __linux__
c1c534
+
c1c534
+unsigned int
c1c534
+virHostCPUGetMicrocodeVersion(void)
c1c534
+{
c1c534
+    char *outbuf = NULL;
c1c534
+    char *cur;
c1c534
+    unsigned int version = 0;
c1c534
+
c1c534
+    if (virFileReadHeaderQuiet(CPUINFO_PATH, 4096, &outbuf) < 0) {
c1c534
+        char ebuf[1024];
c1c534
+        VIR_DEBUG("Failed to read microcode version from %s: %s",
c1c534
+                  CPUINFO_PATH, virStrerror(errno, ebuf, sizeof(ebuf)));
c1c534
+        return 0;
c1c534
+    }
c1c534
+
c1c534
+    /* Account for format 'microcode    : XXXX'*/
c1c534
+    if (!(cur = strstr(outbuf, "microcode")) ||
c1c534
+        !(cur = strchr(cur, ':')))
c1c534
+        goto cleanup;
c1c534
+    cur++;
c1c534
+
c1c534
+    /* Linux places the microcode revision in a 32-bit integer, so
c1c534
+     * ui is fine for us too.  */
c1c534
+    if (virStrToLong_ui(cur, &cur, 0, &version) < 0)
c1c534
+        goto cleanup;
c1c534
+
c1c534
+ cleanup:
c1c534
+    VIR_FREE(outbuf);
c1c534
+    return version;
c1c534
+}
c1c534
+
c1c534
+#else
c1c534
+
c1c534
+unsigned int
c1c534
+virHostCPUGetMicrocodeVersion(void)
c1c534
+{
c1c534
+    return 0;
c1c534
+}
c1c534
+
c1c534
+#endif
c1c534
diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
c1c534
index 67033de842..f9f3359288 100644
c1c534
--- a/src/util/virhostcpu.h
c1c534
+++ b/src/util/virhostcpu.h
c1c534
@@ -66,4 +66,6 @@ virBitmapPtr virHostCPUGetSiblingsList(unsigned int cpu);
c1c534
 
c1c534
 int virHostCPUGetOnline(unsigned int cpu, bool *online);
c1c534
 
c1c534
+unsigned int virHostCPUGetMicrocodeVersion(void);
c1c534
+
c1c534
 #endif /* __VIR_HOSTCPU_H__*/
c1c534
-- 
c1c534
2.15.1
c1c534