From 1f1995f786d1b26ff9867630485928b112503fa5 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin <markmc@redhat.com> Date: Wed, 1 Jul 2009 23:13:14 +0100 Subject: [PATCH 1/4] net: avoid leaking VLANClientState on PCI NIC hot remove https://bugzilla.redhat.com/500977 https://bugzilla.redhat.com/500978 https://bugzilla.redhat.com/500980 In device-hotplug.c:destroy_nic() we require: a) NICInfo::private matches the PCIDevice being removed and b) VLANClientState::opaque also matches the PCIDevice In the case of rtl8139, ne2k_pci and eepro100, the vc->opaque pointer isn't actually to a PCIDevice. Fix the problem by making the relationship between a NICInfo and it's corresponding VLANClientState much more clear rather than finding it via fragile pointer matching. The upstream code has changed a bit in this area, but I've suggested a similar fix upstream: http://lists.gnu.org/archive/html/qemu-devel/2009-07/msg00049.html Signed-off-by: Mark McLoughlin <markmc@redhat.com> Message-Id: <1246486394.598.93.camel@blaa> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> Bugzilla: 500977 Bugzilla: 500978 Bugzilla: 500980 RH-Upstream-status: similar-fix-submitted Acked-by: Juan Quintela <quintela@redhat.com> Acked-by: Don Dutile <ddutile@redhat.com> Acked-by: Marcelo Tosatti <mtosatti@redhat.com> --- qemu/hw/device-hotplug.c | 7 +------ qemu/hw/e1000.c | 1 + qemu/hw/eepro100.c | 1 + qemu/hw/ne2000.c | 1 + qemu/hw/pcnet.c | 1 + qemu/hw/rtl8139.c | 1 + qemu/hw/virtio-net.c | 1 + qemu/net.h | 1 + 8 files changed, 8 insertions(+), 6 deletions(-) diff --git a/qemu/hw/device-hotplug.c b/qemu/hw/device-hotplug.c index 3bdc048..e178083 100644 --- a/qemu/hw/device-hotplug.c +++ b/qemu/hw/device-hotplug.c @@ -55,12 +55,7 @@ void destroy_nic(dev_match_fn *match_fn, void *arg) nic = &nd_table[i]; if (nic->used) { if (nic->private && match_fn(nic->private, arg)) { - if (nic->vlan) { - VLANClientState *vc; - vc = qemu_find_vlan_client(nic->vlan, nic->private); - if (vc) - qemu_del_vlan_client(vc); - } + qemu_del_vlan_client(nic->vc); net_client_uninit(nic); } } diff --git a/qemu/hw/e1000.c b/qemu/hw/e1000.c index cd47f94..d12e14f 100644 --- a/qemu/hw/e1000.c +++ b/qemu/hw/e1000.c @@ -1123,6 +1123,7 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn) d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, e1000_receive, e1000_can_receive, d); + nd->vc = d->vc; d->vc->cleanup = e1000_cleanup; d->vc->link_status_changed = e1000_set_link_status; diff --git a/qemu/hw/eepro100.c b/qemu/hw/eepro100.c index 0061ea7..72fc54f 100644 --- a/qemu/hw/eepro100.c +++ b/qemu/hw/eepro100.c @@ -1780,6 +1780,7 @@ static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd, s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, nic_receive, nic_can_receive, s); + nd->vc = s->vc; qemu_format_nic_info_str(s->vc, s->macaddr); diff --git a/qemu/hw/ne2000.c b/qemu/hw/ne2000.c index 7c00017..d24c547 100644 --- a/qemu/hw/ne2000.c +++ b/qemu/hw/ne2000.c @@ -811,6 +811,7 @@ PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn) ne2000_reset(s); s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, ne2000_receive, ne2000_can_receive, s); + nd->vc = s->vc; qemu_format_nic_info_str(s->vc, s->macaddr); diff --git a/qemu/hw/pcnet.c b/qemu/hw/pcnet.c index 9dfc922..470d0ed 100644 --- a/qemu/hw/pcnet.c +++ b/qemu/hw/pcnet.c @@ -1946,6 +1946,7 @@ static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str, if (nd && nd->vlan) { d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, pcnet_receive, pcnet_can_receive, d); + nd->vc = d->vc; d->vc->cleanup = cleanup; qemu_format_nic_info_str(d->vc, d->nd->macaddr); diff --git a/qemu/hw/rtl8139.c b/qemu/hw/rtl8139.c index d1d50ee..ac5b3cf 100644 --- a/qemu/hw/rtl8139.c +++ b/qemu/hw/rtl8139.c @@ -3459,6 +3459,7 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn) rtl8139_reset(s); s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, rtl8139_receive, rtl8139_can_receive, s); + nd->vc = s->vc; qemu_format_nic_info_str(s->vc, s->macaddr); diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c index a505c83..54a965e 100644 --- a/qemu/hw/virtio-net.c +++ b/qemu/hw/virtio-net.c @@ -476,6 +476,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) n->status = VIRTIO_NET_S_LINK_UP; n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, virtio_net_receive, virtio_net_can_receive, n); + nd->vc = n->vc; n->vc->cleanup = virtio_net_cleanup; n->vc->link_status_changed = virtio_net_set_link_status; n->vc->fd_read_raw = virtio_net_receive_raw; diff --git a/qemu/net.h b/qemu/net.h index f4806c0..47a2461 100644 --- a/qemu/net.h +++ b/qemu/net.h @@ -74,6 +74,7 @@ struct NICInfo { const char *model; const char *name; VLANState *vlan; + VLANClientState *vc; void *private; int used; }; -- 1.6.3.rc4.29.g8146