diff options
author | Johan Hovold <jhovold@gmail.com> | 2012-10-17 18:31:33 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-18 00:48:00 +0400 |
commit | bf90ff5f3b8f67e5b42df4ea4fd543f8010a2676 (patch) | |
tree | b29ae0d832c7aa83b74e0c19c90eeb11b7027df2 /drivers/usb/serial/spcp8x5.c | |
parent | 638b9e15233c9570bce65301aa9877235316b9f0 (diff) | |
download | linux-bf90ff5f3b8f67e5b42df4ea4fd543f8010a2676.tar.xz |
USB: spcp8x5: fix port-data memory leak
Fix port-data memory leak by replacing attach and release with
port_probe and port_remove.
Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no
driver is bound) the port private data is no longer freed at release as
it is no longer accessible.
Compile-only tested.
Cc: <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/spcp8x5.c')
-rw-r--r-- | drivers/usb/serial/spcp8x5.c | 46 |
1 files changed, 18 insertions, 28 deletions
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 9716efe92955..769c137f8975 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -157,13 +157,10 @@ struct spcp8x5_private { u8 line_status; }; -/* desc : when device plug in,this function would be called. - * thanks to usb_serial subsystem,then do almost every things for us. And what - * we should do just alloc the buffer */ -static int spcp8x5_startup(struct usb_serial *serial) +static int spcp8x5_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct spcp8x5_private *priv; - int i; enum spcp8x5_type type = SPCP825_007_TYPE; u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); @@ -180,34 +177,27 @@ static int spcp8x5_startup(struct usb_serial *serial) type = SPCP825_PHILIP_TYPE; dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type); - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL); - if (!priv) - goto cleanup; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - priv->type = type; - usb_set_serial_port_data(serial->port[i] , priv); - } + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + priv->type = type; + + usb_set_serial_port_data(port , priv); return 0; -cleanup: - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i] , NULL); - } - return -ENOMEM; } -/* call when the device plug out. free all the memory alloced by probe */ -static void spcp8x5_release(struct usb_serial *serial) +static int spcp8x5_port_remove(struct usb_serial_port *port) { - int i; + struct spcp8x5_private *priv; - for (i = 0; i < serial->num_ports; i++) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } /* set the modem control line of the device. @@ -649,8 +639,8 @@ static struct usb_serial_driver spcp8x5_device = { .ioctl = spcp8x5_ioctl, .tiocmget = spcp8x5_tiocmget, .tiocmset = spcp8x5_tiocmset, - .attach = spcp8x5_startup, - .release = spcp8x5_release, + .port_probe = spcp8x5_port_probe, + .port_remove = spcp8x5_port_remove, .process_read_urb = spcp8x5_process_read_urb, }; |