Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755333Ab2JZAWP (ORCPT ); Thu, 25 Oct 2012 20:22:15 -0400 Received: from mail.kernel.org ([198.145.19.201]:53659 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754310Ab2JZAHy (ORCPT ); Thu, 25 Oct 2012 20:07:54 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Greg Kroah-Hartman , alan@lxorguk.ukuu.org.uk, Johan Hovold Subject: [ 37/85] USB: cp210x: fix port-data memory leak Date: Thu, 25 Oct 2012 17:05:55 -0700 Message-Id: <20121026000034.836872293@linuxfoundation.org> X-Mailer: git-send-email 1.7.12.2.421.g261b511 In-Reply-To: <20121026000031.107227138@linuxfoundation.org> References: <20121026000031.107227138@linuxfoundation.org> User-Agent: quilt/0.60-2.1.2 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4375 Lines: 137 3.6-stable review patch. If anyone has any objections, please let me know. ------------------ From: Johan Hovold commit 4295fe7791a1b20c90cbaaa6f23f2fb94218b8a7 upstream. Fix port data memory leak by replacing port private data with serial private data. Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release. The private data is used to store the control interface number, but as this is the same for all ports on an interface it should be stored as usb-serial data anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -164,7 +164,7 @@ static const struct usb_device_id id_tab MODULE_DEVICE_TABLE(usb, id_table); -struct cp210x_port_private { +struct cp210x_serial_private { __u8 bInterfaceNumber; }; @@ -278,7 +278,7 @@ static int cp210x_get_config(struct usb_ unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; @@ -294,7 +294,7 @@ static int cp210x_get_config(struct usb_ /* Issue the request, attempting to read 'size' bytes */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), request, REQTYPE_INTERFACE_TO_HOST, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_GET_TIMEOUT); /* Convert data into an array of integers */ @@ -326,7 +326,7 @@ static int cp210x_set_config(struct usb_ unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; @@ -348,13 +348,13 @@ static int cp210x_set_config(struct usb_ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_SET_TIMEOUT); } else { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, data[0], - port_priv->bInterfaceNumber, NULL, 0, + spriv->bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); } @@ -854,37 +854,30 @@ static void cp210x_break_ctl (struct tty static int cp210x_startup(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct usb_host_interface *cur_altsetting; + struct cp210x_serial_private *spriv; /* cp210x buffers behave strangely unless device is reset */ usb_reset_device(serial->dev); - for (i = 0; i < serial->num_ports; i++) { - port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); - if (!port_priv) - return -ENOMEM; - - memset(port_priv, 0x00, sizeof(*port_priv)); - port_priv->bInterfaceNumber = - serial->interface->cur_altsetting->desc.bInterfaceNumber; + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; - usb_set_serial_port_data(serial->port[i], port_priv); - } + cur_altsetting = serial->interface->cur_altsetting; + spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber; + + usb_set_serial_data(serial, spriv); return 0; } static void cp210x_release(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct cp210x_serial_private *spriv; - for (i = 0; i < serial->num_ports; i++) { - port_priv = usb_get_serial_port_data(serial->port[i]); - kfree(port_priv); - usb_set_serial_port_data(serial->port[i], NULL); - } + spriv = usb_get_serial_data(serial); + kfree(spriv); } module_usb_serial_driver(serial_drivers, id_table); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/