Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > media > main-src > by-pkgid > aadbe78a25743146bb784eee19f007c5 > files > 479

kvm-83-164.el5_5.9.src.rpm

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