提交 50348e6e 编写于 作者: P Peter Krempa

qemu: Remove hostdev entry when freeing the depending network entry

When using a <interface type="network"> that points to a network with
hostdev forwarding mode a hostdev alias is created for the network. This
allias is inserted into the hostdev list, but is backed with a part of
the network object that it is connected to.

When a VM is being stopped qemuProcessStop() calls
networkReleaseActualDevice() which eventually frees the memory for the
hostdev object. Afterwards when the domain definition is being freed by
virDomainDefFree() an invalid pointer is accessed by
virDomainHostdevDefFree() and may cause a crash of the daemon.

This patch removes the entry in the hostdev list before freeing the
depending memory to avoid this issue.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1000973
上级 8aecd351
...@@ -9965,26 +9965,36 @@ virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net) ...@@ -9965,26 +9965,36 @@ virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net)
return matchidx; return matchidx;
} }
virDomainNetDefPtr
virDomainNetRemove(virDomainDefPtr def, size_t i)
{
virDomainNetDefPtr net = def->nets[i];
void
virDomainNetRemoveHostdev(virDomainDefPtr def,
virDomainNetDefPtr net)
{
if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) { if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
/* hostdev net devices are normally also be in the hostdevs /* hostdev net devices are normally also be in the hostdevs
* array, but might have already been removed by the time we * array, but might have already been removed by the time we
* get here. * get here.
*/ */
virDomainHostdevDefPtr hostdev = &net->data.hostdev.def; virDomainHostdevDefPtr hostdev = &net->data.hostdev.def;
size_t h; size_t i;
for (h = 0; h < def->nhostdevs; h++) { for (i = 0; i < def->nhostdevs; i++) {
if (def->hostdevs[h] == hostdev) { if (def->hostdevs[i] == hostdev) {
virDomainHostdevRemove(def, h); virDomainHostdevRemove(def, i);
break; break;
} }
} }
} }
}
virDomainNetDefPtr
virDomainNetRemove(virDomainDefPtr def, size_t i)
{
virDomainNetDefPtr net = def->nets[i];
virDomainNetRemoveHostdev(def, net);
if (def->nnets > 1) { if (def->nnets > 1) {
memmove(def->nets + i, memmove(def->nets + i,
def->nets + i + 1, def->nets + i + 1,
......
...@@ -2371,6 +2371,7 @@ int virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net); ...@@ -2371,6 +2371,7 @@ int virDomainNetFindIdx(virDomainDefPtr def, virDomainNetDefPtr net);
virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device); virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device);
int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net); int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net);
virDomainNetDefPtr virDomainNetRemove(virDomainDefPtr def, size_t i); virDomainNetDefPtr virDomainNetRemove(virDomainDefPtr def, size_t i);
void virDomainNetRemoveHostdev(virDomainDefPtr def, virDomainNetDefPtr net);
int virDomainHostdevInsert(virDomainDefPtr def, virDomainHostdevDefPtr hostdev); int virDomainHostdevInsert(virDomainDefPtr def, virDomainHostdevDefPtr hostdev);
virDomainHostdevDefPtr virDomainHostdevDefPtr
......
...@@ -303,6 +303,7 @@ virDomainNetGetActualVirtPortProfile; ...@@ -303,6 +303,7 @@ virDomainNetGetActualVirtPortProfile;
virDomainNetGetActualVlan; virDomainNetGetActualVlan;
virDomainNetInsert; virDomainNetInsert;
virDomainNetRemove; virDomainNetRemove;
virDomainNetRemoveHostdev;
virDomainNetTypeToString; virDomainNetTypeToString;
virDomainNostateReasonTypeFromString; virDomainNostateReasonTypeFromString;
virDomainNostateReasonTypeToString; virDomainNostateReasonTypeToString;
......
...@@ -1066,6 +1066,8 @@ cleanup: ...@@ -1066,6 +1066,8 @@ cleanup:
virDomainNetGetActualBridgeName(net), net->ifname)); virDomainNetGetActualBridgeName(net), net->ifname));
} }
virDomainNetRemoveHostdev(vm->def, net);
networkReleaseActualDevice(net); networkReleaseActualDevice(net);
} }
...@@ -2107,6 +2109,9 @@ qemuDomainChangeNet(virQEMUDriverPtr driver, ...@@ -2107,6 +2109,9 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
/* the changes above warrant replacing olddev with newdev in /* the changes above warrant replacing olddev with newdev in
* the domain's nets list. * the domain's nets list.
*/ */
/* this function doesn't work with HOSTDEV networks yet, thus
* no need to change the pointer in the hostdev structure */
networkReleaseActualDevice(olddev); networkReleaseActualDevice(olddev);
virDomainNetDefFree(olddev); virDomainNetDefFree(olddev);
/* move newdev into the nets list, and NULL it out from the /* move newdev into the nets list, and NULL it out from the
......
...@@ -4259,6 +4259,8 @@ void qemuProcessStop(virQEMUDriverPtr driver, ...@@ -4259,6 +4259,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
virDomainNetGetActualBridgeName(net), virDomainNetGetActualBridgeName(net),
net->ifname)); net->ifname));
/* kick the device out of the hostdev list too */
virDomainNetRemoveHostdev(def, net);
networkReleaseActualDevice(net); networkReleaseActualDevice(net);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册