render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
25aafc
From 9bf517748d9fed50a0bee163625f119b25fdb0ea Mon Sep 17 00:00:00 2001
25aafc
Message-Id: <9bf517748d9fed50a0bee163625f119b25fdb0ea@dist-git>
25aafc
From: Laine Stump <laine@redhat.com>
25aafc
Date: Thu, 26 Sep 2019 18:05:26 -0400
25aafc
Subject: [PATCH] conf: utility function to update entry in def->nets array
25aafc
25aafc
A virDomainNetDef object in a domain's nets array might contain a
25aafc
virDomainHostdevDef, and when this is the case, the domain's hostdevs
25aafc
array will also have a pointer to this embedded hostdev (this is done
25aafc
so that internal functions that need to perform some operation on all
25aafc
hostdevs won't leave out the type='hostdev' network interfaces).
25aafc
25aafc
When a network device was updated with virDomainUpdateDeviceFlags(),
25aafc
we were replacing the entry in the nets array (and free'ing the
25aafc
original) but forgetting about the pointer in the hostdevs array
25aafc
(which would then point to the now-free'd hostdev contained in the old
25aafc
net object.) This often resulted in a libvirtd crash.
25aafc
25aafc
The solution is to add a function, virDomainNetUpdate(), called by
25aafc
qemuDomainUpdateDeviceConfig(), that updates the hostdevs array
25aafc
appropriately along with the nets array.
25aafc
25aafc
Resolves: https://bugzilla.redhat.com/1558934
25aafc
25aafc
Signed-off-by: Laine Stump <laine@redhat.com>
25aafc
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
25aafc
(cherry picked from commit 7e490cdad6364c82b326d5d9251826c757e8f77b)
25aafc
Message-Id: <20190926220526.12970-1-laine@redhat.com>
25aafc
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
25aafc
---
25aafc
 src/conf/domain_conf.c   | 41 ++++++++++++++++++++++++++++++++++++++++
25aafc
 src/conf/domain_conf.h   |  1 +
25aafc
 src/libvirt_private.syms |  1 +
25aafc
 src/lxc/lxc_driver.c     |  6 ++++--
25aafc
 src/qemu/qemu_driver.c   |  6 ++++--
25aafc
 5 files changed, 51 insertions(+), 4 deletions(-)
25aafc
25aafc
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
25aafc
index 0352fad245..60f426df04 100644
25aafc
--- a/src/conf/domain_conf.c
25aafc
+++ b/src/conf/domain_conf.c
25aafc
@@ -17119,6 +17119,47 @@ virDomainNetRemove(virDomainDefPtr def, size_t i)
25aafc
     return net;
25aafc
 }
25aafc
 
25aafc
+
25aafc
+int
25aafc
+virDomainNetUpdate(virDomainDefPtr def,
25aafc
+                   size_t netidx,
25aafc
+                   virDomainNetDefPtr newnet)
25aafc
+{
25aafc
+    size_t hostdevidx;
25aafc
+    virDomainNetDefPtr oldnet = def->nets[netidx];
25aafc
+    virDomainHostdevDefPtr oldhostdev = virDomainNetGetActualHostdev(oldnet);
25aafc
+    virDomainHostdevDefPtr newhostdev = virDomainNetGetActualHostdev(newnet);
25aafc
+
25aafc
+    /*
25aafc
+     * if newnet or oldnet has a valid hostdev*, we need to update the
25aafc
+     * hostdevs list
25aafc
+     */
25aafc
+    if (oldhostdev) {
25aafc
+        for (hostdevidx = 0; hostdevidx < def->nhostdevs; hostdevidx++) {
25aafc
+            if (def->hostdevs[hostdevidx] == oldhostdev)
25aafc
+                break;
25aafc
+        }
25aafc
+    }
25aafc
+
25aafc
+    if (oldhostdev && hostdevidx < def->nhostdevs) {
25aafc
+        if (newhostdev) {
25aafc
+            /* update existing entry in def->hostdevs */
25aafc
+            def->hostdevs[hostdevidx] = newhostdev;
25aafc
+        } else {
25aafc
+            /* delete oldhostdev from def->hostdevs */
25aafc
+            virDomainHostdevRemove(def, hostdevidx);
25aafc
+        }
25aafc
+    } else if (newhostdev) {
25aafc
+        /* add newhostdev to end of def->hostdevs */
25aafc
+        if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, newhostdev) < 0)
25aafc
+            return -1;
25aafc
+    }
25aafc
+
25aafc
+    def->nets[netidx] = newnet;
25aafc
+    return 0;
25aafc
+}
25aafc
+
25aafc
+
25aafc
 int virDomainControllerInsert(virDomainDefPtr def,
25aafc
                               virDomainControllerDefPtr controller)
25aafc
 {
25aafc
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
25aafc
index 1c4556cecd..ef8f061ae2 100644
25aafc
--- a/src/conf/domain_conf.h
25aafc
+++ b/src/conf/domain_conf.h
25aafc
@@ -3168,6 +3168,7 @@ virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device);
25aafc
 virDomainNetDefPtr virDomainNetFindByName(virDomainDefPtr def, const char *ifname);
25aafc
 bool virDomainHasNet(virDomainDefPtr def, virDomainNetDefPtr net);
25aafc
 int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net);
25aafc
+int virDomainNetUpdate(virDomainDefPtr def, size_t netidx, virDomainNetDefPtr newnet);
25aafc
 virDomainNetDefPtr virDomainNetRemove(virDomainDefPtr def, size_t i);
25aafc
 void virDomainNetRemoveHostdev(virDomainDefPtr def, virDomainNetDefPtr net);
25aafc
 
25aafc
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
25aafc
index 9b5e1350f0..b213e5764b 100644
25aafc
--- a/src/libvirt_private.syms
25aafc
+++ b/src/libvirt_private.syms
25aafc
@@ -476,6 +476,7 @@ virDomainNetSetDeviceImpl;
25aafc
 virDomainNetTypeFromString;
25aafc
 virDomainNetTypeSharesHostView;
25aafc
 virDomainNetTypeToString;
25aafc
+virDomainNetUpdate;
25aafc
 virDomainNostateReasonTypeFromString;
25aafc
 virDomainNostateReasonTypeToString;
25aafc
 virDomainObjAssignDef;
25aafc
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
25aafc
index 5978183e7f..0f2ef47bb5 100644
25aafc
--- a/src/lxc/lxc_driver.c
25aafc
+++ b/src/lxc/lxc_driver.c
25aafc
@@ -3526,8 +3526,10 @@ lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
25aafc
                                          false) < 0)
25aafc
             return -1;
25aafc
 
25aafc
-        virDomainNetDefFree(vmdef->nets[idx]);
25aafc
-        vmdef->nets[idx] = net;
25aafc
+        if (virDomainNetUpdate(vmdef, idx, net) < 0)
25aafc
+            return -1;
25aafc
+
25aafc
+        virDomainNetDefFree(oldDev.data.net);
25aafc
         dev->data.net = NULL;
25aafc
         ret = 0;
25aafc
 
25aafc
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
25aafc
index d95c97928d..2852b96edd 100644
25aafc
--- a/src/qemu/qemu_driver.c
25aafc
+++ b/src/qemu/qemu_driver.c
25aafc
@@ -8341,8 +8341,10 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
25aafc
                                          false) < 0)
25aafc
             return -1;
25aafc
 
25aafc
-        virDomainNetDefFree(vmdef->nets[pos]);
25aafc
-        vmdef->nets[pos] = net;
25aafc
+        if (virDomainNetUpdate(vmdef, pos, net))
25aafc
+            return -1;
25aafc
+
25aafc
+        virDomainNetDefFree(oldDev.data.net);
25aafc
         dev->data.net = NULL;
25aafc
         break;
25aafc
 
25aafc
-- 
25aafc
2.23.0
25aafc