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