904b1d4
From 3675a0dde74f890404f392e194f1adc6b24285f7 Mon Sep 17 00:00:00 2001
1c9931d
From: Glauber Costa <glommer@redhat.com>
1c9931d
Date: Wed, 23 Sep 2009 09:49:43 +0100
1c9931d
Subject: [PATCH] Correctly free nd structure
1c9931d
1c9931d
When we "free" a NICInfo structure, we can leak pointers, since we don't do
1c9931d
much more than setting used = 0.
1c9931d
1c9931d
We free() the model parameter, but we don't set it to NULL. This means that
1c9931d
a new user of this structure will see garbage in there. It was not noticed
1c9931d
before because reusing a NICInfo is not that common, but it can be, for
1c9931d
users of device pci hotplug.
1c9931d
1c9931d
A user hit it, described at https://bugzilla.redhat.com/524022
1c9931d
1c9931d
This patch memset's the whole structure, guaranteeing that anyone reusing it
1c9931d
will see a fresh NICinfo. Also, we free some other strings that are currently
1c9931d
leaking.
1c9931d
1c9931d
This codebase is quite old, so this patch should feed all stable trees.
1c9931d
1c9931d
Signed-off-by: Glauber Costa <glommer@redhat.com>
1c9931d
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
1c9931d
Fedora-patch: qemu-correctly-free-nic-info-structure.patch
1c9931d
---
1c9931d
 net.c |   16 +++++++++++-----
1c9931d
 net.h |    8 ++++----
1c9931d
 vl.c  |    2 +-
1c9931d
 3 files changed, 16 insertions(+), 10 deletions(-)
1c9931d
1c9931d
diff --git a/net.c b/net.c
904b1d4
index a1c1111..da2f428 100644
1c9931d
--- a/net.c
1c9931d
+++ b/net.c
904b1d4
@@ -2559,7 +2559,7 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models,
1c9931d
     int i, exit_status = 0;
1c9931d
 
1c9931d
     if (!nd->model)
1c9931d
-        nd->model = strdup(default_model);
1c9931d
+        nd->model = qemu_strdup(default_model);
1c9931d
 
1c9931d
     if (strcmp(nd->model, "?") != 0) {
1c9931d
         for (i = 0 ; models[i]; i++)
904b1d4
@@ -2629,6 +2629,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
1c9931d
             goto out;
1c9931d
         }
1c9931d
         nd = &nd_table[idx];
1c9931d
+        memset(nd, 0, sizeof(*nd));
1c9931d
         macaddr = nd->macaddr;
1c9931d
         macaddr[0] = 0x52;
1c9931d
         macaddr[1] = 0x54;
904b1d4
@@ -2645,13 +2646,13 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
1c9931d
             }
1c9931d
         }
1c9931d
         if (get_param_value(buf, sizeof(buf), "model", p)) {
1c9931d
-            nd->model = strdup(buf);
1c9931d
+            nd->model = qemu_strdup(buf);
1c9931d
         }
1c9931d
         if (get_param_value(buf, sizeof(buf), "addr", p)) {
1c9931d
-            nd->devaddr = strdup(buf);
1c9931d
+            nd->devaddr = qemu_strdup(buf);
1c9931d
         }
1c9931d
         if (get_param_value(buf, sizeof(buf), "id", p)) {
1c9931d
-            nd->id = strdup(buf);
1c9931d
+            nd->id = qemu_strdup(buf);
1c9931d
         }
1c9931d
         nd->nvectors = NIC_NVECTORS_UNSPECIFIED;
1c9931d
         if (get_param_value(buf, sizeof(buf), "vectors", p)) {
904b1d4
@@ -2998,8 +2999,13 @@ void net_client_uninit(NICInfo *nd)
1c9931d
 {
1c9931d
     nd->vlan->nb_guest_devs--;
1c9931d
     nb_nics--;
1c9931d
+
1c9931d
+    qemu_free(nd->model);
1c9931d
+    qemu_free(nd->name);
1c9931d
+    qemu_free(nd->devaddr);
1c9931d
+    qemu_free(nd->id);
1c9931d
+
1c9931d
     nd->used = 0;
1c9931d
-    free((void *)nd->model);
1c9931d
 }
1c9931d
 
1c9931d
 static int net_host_check_device(const char *device)
1c9931d
diff --git a/net.h b/net.h
904b1d4
index 57ab031..94db0d7 100644
1c9931d
--- a/net.h
1c9931d
+++ b/net.h
904b1d4
@@ -101,10 +101,10 @@ enum {
1c9931d
 
1c9931d
 struct NICInfo {
1c9931d
     uint8_t macaddr[6];
1c9931d
-    const char *model;
1c9931d
-    const char *name;
1c9931d
-    const char *devaddr;
1c9931d
-    const char *id;
1c9931d
+    char *model;
1c9931d
+    char *name;
1c9931d
+    char *devaddr;
1c9931d
+    char *id;
1c9931d
     VLANState *vlan;
1c9931d
     VLANClientState *vc;
1c9931d
     void *private;
1c9931d
diff --git a/vl.c b/vl.c
1c9931d
index 26bced8..d7c7ab1 100644
1c9931d
--- a/vl.c
1c9931d
+++ b/vl.c
1c9931d
@@ -2594,7 +2594,7 @@ static int usb_device_add(const char *devname, int is_hotplug)
1c9931d
 
1c9931d
         if (net_client_init(NULL, "nic", p) < 0)
1c9931d
             return -1;
1c9931d
-        nd_table[nic].model = "usb";
1c9931d
+        nd_table[nic].model = qemu_strdup("usb");
1c9931d
         dev = usb_net_init(&nd_table[nic]);
1c9931d
     } else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
1c9931d
         dev = usb_bt_init(devname[2] ? hci_init(p) :
1c9931d
-- 
1c9931d
1.6.2.5
1c9931d