[PATCH 5/7] virHostCPUGetCPUID: Fix possible allocation of huge amount of memory

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In case when the 'KVM_GET_SUPPORTED_CPUID' ioctl on /dev/kvm would
fail for other reason than the documented E2BIG, our code would continue
looping and calling it while always increasing the memory buffer even
when that will not help.

Rewrite the function to allow another iteration only with the correct
errno.

Additionally rename the 'i' variable to 'alloc_size' as it's not a pure
iterator.

Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx>
---
 src/util/virhostcpu.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
index f07514a11b..aa21c567be 100644
--- a/src/util/virhostcpu.c
+++ b/src/util/virhostcpu.c
@@ -1345,7 +1345,7 @@ virHostCPUGetCPUIDFilterVolatile(struct kvm_cpuid2 *kvm_cpuid)
 struct kvm_cpuid2 *
 virHostCPUGetCPUID(void)
 {
-    size_t i;
+    size_t alloc_size;
     VIR_AUTOCLOSE fd = open(KVM_DEVICE, O_RDONLY);

     if (fd < 0) {
@@ -1360,16 +1360,26 @@ virHostCPUGetCPUID(void)
      * the 'nent' field is adjusted and an error (ENOMEM) is returned.  If the
      * number is just right, the 'nent' field is adjusted to the number of valid
      * entries in the 'entries' array, which is then filled. */
-    for (i = 1; i < INT32_MAX; i *= 2) {
+    for (alloc_size = 1; alloc_size < INT32_MAX; alloc_size *= 2) {
         g_autofree struct kvm_cpuid2 *kvm_cpuid = NULL;
+
         kvm_cpuid = g_malloc0(sizeof(struct kvm_cpuid2) +
-                              sizeof(struct kvm_cpuid_entry2) * i);
-        kvm_cpuid->nent = i;
+                              sizeof(struct kvm_cpuid_entry2) * alloc_size);
+        kvm_cpuid->nent = alloc_size;

         if (ioctl(fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid) == 0) {
             virHostCPUGetCPUIDFilterVolatile(kvm_cpuid);
             return g_steal_pointer(&kvm_cpuid);
         }
+
+        /* enlarge the buffer and try again */
+        if (errno == E2BIG) {
+            VIR_DEBUG("looping %zu", alloc_size);
+            continue;
+        }
+
+        /* we fail on any other error code to prevent pointless looping */
+        break;
     }

     virReportSystemError(errno, "%s", _("Cannot read host CPUID"));
-- 
2.35.1




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux