76d3df6
From aa4a3dce1c88ed51b616806b8214b7c8428b7470 Mon Sep 17 00:00:00 2001
76d3df6
From: P J P <ppandit@redhat.com>
76d3df6
Date: Tue, 15 Dec 2015 12:27:54 +0530
76d3df6
Subject: [PATCH] net: vmxnet3: avoid memory leakage in activate_device
76d3df6
76d3df6
Vmxnet3 device emulator does not check if the device is active
76d3df6
before activating it, also it did not free the transmit & receive
76d3df6
buffers while deactivating the device, thus resulting in memory
76d3df6
leakage on the host. This patch fixes both these issues to avoid
76d3df6
host memory leakage.
76d3df6
76d3df6
Reported-by: Qinghao Tang <luodalongde@gmail.com>
76d3df6
Reviewed-by: Dmitry Fleytman <dmitry@daynix.com>
76d3df6
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
76d3df6
Cc: qemu-stable@nongnu.org
76d3df6
Signed-off-by: Jason Wang <jasowang@redhat.com>
76d3df6
---
76d3df6
 tools/qemu-xen/hw/net/vmxnet3.c |   24 ++++++++++++++++--------
76d3df6
 1 files changed, 16 insertions(+), 8 deletions(-)
76d3df6
76d3df6
diff --git a/tools/qemu-xen/hw/net/vmxnet3.c b/tools/qemu-xen/hw/net/vmxnet3.c
76d3df6
index a5dd79a..9c1adfc 100644
76d3df6
--- a/tools/qemu-xen/hw/net/vmxnet3.c
76d3df6
+++ b/tools/qemu-xen/hw/net/vmxnet3.c
76d3df6
@@ -1194,8 +1194,13 @@ static void vmxnet3_reset_mac(VMXNET3State *s)
76d3df6
 
76d3df6
 static void vmxnet3_deactivate_device(VMXNET3State *s)
76d3df6
 {
76d3df6
-    VMW_CBPRN("Deactivating vmxnet3...");
76d3df6
-    s->device_active = false;
76d3df6
+    if (s->device_active) {
76d3df6
+        VMW_CBPRN("Deactivating vmxnet3...");
76d3df6
+        vmxnet_tx_pkt_reset(s->tx_pkt);
76d3df6
+        vmxnet_tx_pkt_uninit(s->tx_pkt);
76d3df6
+        vmxnet_rx_pkt_uninit(s->rx_pkt);
76d3df6
+        s->device_active = false;
76d3df6
+    }
76d3df6
 }
76d3df6
 
76d3df6
 static void vmxnet3_reset(VMXNET3State *s)
76d3df6
@@ -1204,7 +1209,6 @@ static void vmxnet3_reset(VMXNET3State *s)
76d3df6
 
76d3df6
     vmxnet3_deactivate_device(s);
76d3df6
     vmxnet3_reset_interrupt_states(s);
76d3df6
-    vmxnet_tx_pkt_reset(s->tx_pkt);
76d3df6
     s->drv_shmem = 0;
76d3df6
     s->tx_sop = true;
76d3df6
     s->skip_current_tx_pkt = false;
76d3df6
@@ -1431,6 +1435,12 @@ static void vmxnet3_activate_device(VMXNET3State *s)
76d3df6
         return;
76d3df6
     }
76d3df6
 
76d3df6
+    /* Verify if device is active */
76d3df6
+    if (s->device_active) {
76d3df6
+        VMW_CFPRN("Vmxnet3 device is active");
76d3df6
+        return;
76d3df6
+    }
76d3df6
+
76d3df6
     vmxnet3_adjust_by_guest_type(s);
76d3df6
     vmxnet3_update_features(s);
76d3df6
     vmxnet3_update_pm_state(s);
76d3df6
@@ -1627,7 +1637,7 @@ static void vmxnet3_handle_command(VMXNET3State *s, uint64_t cmd)
76d3df6
         break;
76d3df6
 
76d3df6
     case VMXNET3_CMD_QUIESCE_DEV:
76d3df6
-        VMW_CBPRN("Set: VMXNET3_CMD_QUIESCE_DEV - pause the device");
76d3df6
+        VMW_CBPRN("Set: VMXNET3_CMD_QUIESCE_DEV - deactivate the device");
76d3df6
         vmxnet3_deactivate_device(s);
76d3df6
         break;
76d3df6
 
76d3df6
@@ -1741,7 +1751,7 @@ vmxnet3_io_bar1_write(void *opaque,
76d3df6
          * shared address only after we get the high part
76d3df6
          */
76d3df6
         if (val == 0) {
76d3df6
-            s->device_active = false;
76d3df6
+            vmxnet3_deactivate_device(s);
76d3df6
         }
76d3df6
         s->temp_shared_guest_driver_memory = val;
76d3df6
         s->drv_shmem = 0;
76d3df6
@@ -2021,9 +2031,7 @@ static bool vmxnet3_peer_has_vnet_hdr(VMXNET3State *s)
76d3df6
 static void vmxnet3_net_uninit(VMXNET3State *s)
76d3df6
 {
76d3df6
     g_free(s->mcast_list);
76d3df6
-    vmxnet_tx_pkt_reset(s->tx_pkt);
76d3df6
-    vmxnet_tx_pkt_uninit(s->tx_pkt);
76d3df6
-    vmxnet_rx_pkt_uninit(s->rx_pkt);
76d3df6
+    vmxnet3_deactivate_device(s);
76d3df6
     qemu_del_nic(s->nic);
76d3df6
 }
76d3df6
 
76d3df6
-- 
76d3df6
1.7.0.4
76d3df6