From: Glauber Costa Date: Wed, 23 Sep 2009 08:49:43 +0000 (+0100) Subject: Correctly free nd structure X-Git-Tag: qemu-0.11.0-1.fc12^0 X-Git-Url: https://repo.or.cz/w/qemu-kvm/fedora.git/commitdiff_plain/3675a0dde74f890404f392e194f1adc6b24285f7 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 --- diff --git a/net.c b/net.c index a1c1111407..da2f4280c9 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 57ab031bf7..94db0d710b 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 26bced8e75..d7c7ab11fb 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) :