Blame SOURCES/libvirt-qemu-Remove-hostdev-entry-when-freeing-the-depending-network-entry.patch

43fe83
From 0309361905e9b9ee674b740610f49ae273862939 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <0309361905e9b9ee674b740610f49ae273862939.1377873641.git.jdenemar@redhat.com>
43fe83
From: Peter Krempa <pkrempa@redhat.com>
43fe83
Date: Thu, 29 Aug 2013 19:21:11 +0200
43fe83
Subject: [PATCH] qemu: Remove hostdev entry when freeing the depending network
43fe83
 entry
43fe83
43fe83
When using a <interface type="network"> that points to a network with
43fe83
hostdev forwarding mode a hostdev alias is created for the network. This
43fe83
allias is inserted into the hostdev list, but is backed with a part of
43fe83
the network object that it is connected to.
43fe83
43fe83
When a VM is being stopped qemuProcessStop() calls
43fe83
networkReleaseActualDevice() which eventually frees the memory for the
43fe83
hostdev object. Afterwards when the domain definition is being freed by
43fe83
virDomainDefFree() an invalid pointer is accessed by
43fe83
virDomainHostdevDefFree() and may cause a crash of the daemon.
43fe83
43fe83
This patch removes the entry in the hostdev list before freeing the
43fe83
depending memory to avoid this issue.
43fe83
43fe83
Resolves:   https://bugzilla.redhat.com/show_bug.cgi?id=1002669 [7.0]
43fe83
            https://bugzilla.redhat.com/show_bug.cgi?id=1000973 [6.5]
43fe83
(cherry picked from commit 50348e6edfa10ddb61929bf95a1c4820a9614e19)
43fe83
---
43fe83
 src/conf/domain_conf.c   | 26 ++++++++++++++++++--------
43fe83
 src/conf/domain_conf.h   |  1 +
43fe83
 src/libvirt_private.syms |  1 +
43fe83
 src/qemu/qemu_hotplug.c  |  5 +++++
43fe83
 src/qemu/qemu_process.c  |  2 ++
43fe83
 5 files changed, 27 insertions(+), 8 deletions(-)
43fe83
43fe83
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
43fe83
index 01f9bd0..1a20232 100644
43fe83
--- a/src/conf/domain_conf.c
43fe83
+++ b/src/conf/domain_conf.c
43fe83
@@ -9936,26 +9936,36 @@ virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net)
43fe83
     return matchidx;
43fe83
 }
43fe83
 
43fe83
-virDomainNetDefPtr
43fe83
-virDomainNetRemove(virDomainDefPtr def, size_t i)
43fe83
-{
43fe83
-    virDomainNetDefPtr net = def->nets[i];
43fe83
 
43fe83
+void
43fe83
+virDomainNetRemoveHostdev(virDomainDefPtr def,
43fe83
+                          virDomainNetDefPtr net)
43fe83
+{
43fe83
     if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
43fe83
         /* hostdev net devices are normally also be in the hostdevs
43fe83
          * array, but might have already been removed by the time we
43fe83
          * get here.
43fe83
          */
43fe83
         virDomainHostdevDefPtr hostdev = &net->data.hostdev.def;
43fe83
-        size_t h;
43fe83
+        size_t i;
43fe83
 
43fe83
-        for (h = 0; h < def->nhostdevs; h++) {
43fe83
-            if (def->hostdevs[h] == hostdev) {
43fe83
-                virDomainHostdevRemove(def, h);
43fe83
+        for (i = 0; i < def->nhostdevs; i++) {
43fe83
+            if (def->hostdevs[i] == hostdev) {
43fe83
+                virDomainHostdevRemove(def, i);
43fe83
                 break;
43fe83
             }
43fe83
         }
43fe83
     }
43fe83
+}
43fe83
+
43fe83
+
43fe83
+virDomainNetDefPtr
43fe83
+virDomainNetRemove(virDomainDefPtr def, size_t i)
43fe83
+{
43fe83
+    virDomainNetDefPtr net = def->nets[i];
43fe83
+
43fe83
+    virDomainNetRemoveHostdev(def, net);
43fe83
+
43fe83
     if (def->nnets > 1) {
43fe83
         memmove(def->nets + i,
43fe83
                 def->nets + i + 1,
43fe83
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
43fe83
index 536fc96..29ef0f8 100644
43fe83
--- a/src/conf/domain_conf.h
43fe83
+++ b/src/conf/domain_conf.h
43fe83
@@ -2360,6 +2360,7 @@ int virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net);
43fe83
 virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device);
43fe83
 int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net);
43fe83
 virDomainNetDefPtr virDomainNetRemove(virDomainDefPtr def, size_t i);
43fe83
+void virDomainNetRemoveHostdev(virDomainDefPtr def, virDomainNetDefPtr net);
43fe83
 
43fe83
 int virDomainHostdevInsert(virDomainDefPtr def, virDomainHostdevDefPtr hostdev);
43fe83
 virDomainHostdevDefPtr
43fe83
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
43fe83
index faa67ad..e6c23e4 100644
43fe83
--- a/src/libvirt_private.syms
43fe83
+++ b/src/libvirt_private.syms
43fe83
@@ -302,6 +302,7 @@ virDomainNetGetActualVirtPortProfile;
43fe83
 virDomainNetGetActualVlan;
43fe83
 virDomainNetInsert;
43fe83
 virDomainNetRemove;
43fe83
+virDomainNetRemoveHostdev;
43fe83
 virDomainNetTypeToString;
43fe83
 virDomainNostateReasonTypeFromString;
43fe83
 virDomainNostateReasonTypeToString;
43fe83
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
43fe83
index 7a6946e..cbe7072 100644
43fe83
--- a/src/qemu/qemu_hotplug.c
43fe83
+++ b/src/qemu/qemu_hotplug.c
43fe83
@@ -940,6 +940,8 @@ cleanup:
43fe83
                                virDomainNetGetActualBridgeName(net), net->ifname));
43fe83
         }
43fe83
 
43fe83
+        virDomainNetRemoveHostdev(vm->def, net);
43fe83
+
43fe83
         networkReleaseActualDevice(net);
43fe83
     }
43fe83
 
43fe83
@@ -1978,6 +1980,9 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
43fe83
         /* the changes above warrant replacing olddev with newdev in
43fe83
          * the domain's nets list.
43fe83
          */
43fe83
+
43fe83
+        /* this function doesn't work with HOSTDEV networks yet, thus
43fe83
+         * no need to change the pointer in the hostdev structure */
43fe83
         networkReleaseActualDevice(olddev);
43fe83
         virDomainNetDefFree(olddev);
43fe83
         /* move newdev into the nets list, and NULL it out from the
43fe83
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
43fe83
index 0dccac3..6a28356 100644
43fe83
--- a/src/qemu/qemu_process.c
43fe83
+++ b/src/qemu/qemu_process.c
43fe83
@@ -4234,6 +4234,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
43fe83
                                        virDomainNetGetActualBridgeName(net),
43fe83
                                        net->ifname));
43fe83
 
43fe83
+        /* kick the device out of the hostdev list too */
43fe83
+        virDomainNetRemoveHostdev(def, net);
43fe83
         networkReleaseActualDevice(net);
43fe83
     }
43fe83
 
43fe83
-- 
43fe83
1.8.3.2
43fe83