From 2b76390876db26fb279d26de86b2c0b8260ff142 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 61c9649..b58945f 100644 --- a/net.c +++ b/net.c @@ -2564,7 +2564,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++) @@ -2634,6 +2634,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; @@ -2650,13 +2651,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)) { @@ -3003,8 +3004,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 b172691..ec78d0a 100644 --- a/net.h +++ b/net.h @@ -100,10 +100,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