]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 Oct 2012 17:47:16 +0000 (10:47 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 Oct 2012 17:47:16 +0000 (10:47 -0700)
added patches:
usb-cp210x-fix-port-data-memory-leak.patch
usb-kl5kusb105-fix-port-data-memory-leak.patch
usb-spcp8x5-fix-port-data-memory-leak.patch
usb-ti_usb_3410_5052-fix-port-data-memory-leak.patch

queue-3.6/series
queue-3.6/usb-cp210x-fix-port-data-memory-leak.patch [new file with mode: 0644]
queue-3.6/usb-kl5kusb105-fix-port-data-memory-leak.patch [new file with mode: 0644]
queue-3.6/usb-spcp8x5-fix-port-data-memory-leak.patch [new file with mode: 0644]
queue-3.6/usb-ti_usb_3410_5052-fix-port-data-memory-leak.patch [new file with mode: 0644]

index b489a547e1b61d3d11a36187f2881adf86b22683..711508b8b6273174c3fa335151c03565b75c0cbe 100644 (file)
@@ -34,3 +34,7 @@ usb-pl2303-fix-port-data-memory-leak.patch
 usb-ssu100-fix-port-data-memory-leak.patch
 usb-kobil_sct-fix-port-data-memory-leak.patch
 usb-cypress_m8-fix-port-data-memory-leak.patch
+usb-cp210x-fix-port-data-memory-leak.patch
+usb-spcp8x5-fix-port-data-memory-leak.patch
+usb-ti_usb_3410_5052-fix-port-data-memory-leak.patch
+usb-kl5kusb105-fix-port-data-memory-leak.patch
diff --git a/queue-3.6/usb-cp210x-fix-port-data-memory-leak.patch b/queue-3.6/usb-cp210x-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..4abe301
--- /dev/null
@@ -0,0 +1,131 @@
+From 4295fe7791a1b20c90cbaaa6f23f2fb94218b8a7 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 15 Oct 2012 15:47:20 +0200
+Subject: USB: cp210x: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+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 <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
diff --git a/queue-3.6/usb-kl5kusb105-fix-port-data-memory-leak.patch b/queue-3.6/usb-kl5kusb105-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..6807b6f
--- /dev/null
@@ -0,0 +1,131 @@
+From 99a6f73c495c420df826e5b267fb073fd6766fc3 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 17 Oct 2012 13:35:01 +0200
+Subject: USB: kl5kusb105: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 99a6f73c495c420df826e5b267fb073fd6766fc3 upstream.
+
+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.
+
+Note that the write waitqueue was initialised but never used.
+
+Compile-only tested.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/kl5kusb105.c |   68 ++++++++++++++--------------------------
+ 1 file changed, 25 insertions(+), 43 deletions(-)
+
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -62,8 +62,8 @@ static bool debug;
+ /*
+  * Function prototypes
+  */
+-static int  klsi_105_startup(struct usb_serial *serial);
+-static void klsi_105_release(struct usb_serial *serial);
++static int klsi_105_port_probe(struct usb_serial_port *port);
++static int klsi_105_port_remove(struct usb_serial_port *port);
+ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
+ static void klsi_105_close(struct usb_serial_port *port);
+ static void klsi_105_set_termios(struct tty_struct *tty,
+@@ -101,8 +101,8 @@ static struct usb_serial_driver kl5kusb1
+       /*.break_ctl =          klsi_105_break_ctl,*/
+       .tiocmget =             klsi_105_tiocmget,
+       .tiocmset =             klsi_105_tiocmset,
+-      .attach =               klsi_105_startup,
+-      .release =              klsi_105_release,
++      .port_probe =           klsi_105_port_probe,
++      .port_remove =          klsi_105_port_remove,
+       .throttle =             usb_serial_generic_throttle,
+       .unthrottle =           usb_serial_generic_unthrottle,
+       .process_read_urb =     klsi_105_process_read_urb,
+@@ -225,58 +225,40 @@ static int klsi_105_get_line_state(struc
+  * Driver's tty interface functions
+  */
+-static int klsi_105_startup(struct usb_serial *serial)
++static int klsi_105_port_probe(struct usb_serial_port *port)
+ {
+       struct klsi_105_private *priv;
+-      int i;
+-      /* check if we support the product id (see keyspan.c)
+-       * FIXME
+-       */
+-
+-      /* allocate the private data structure */
+-      for (i = 0; i < serial->num_ports; i++) {
+-              priv = kmalloc(sizeof(struct klsi_105_private),
+-                                                 GFP_KERNEL);
+-              if (!priv) {
+-                      dbg("%skmalloc for klsi_105_private failed.", __func__);
+-                      i--;
+-                      goto err_cleanup;
+-              }
+-              /* set initial values for control structures */
+-              priv->cfg.pktlen    = 5;
+-              priv->cfg.baudrate  = kl5kusb105a_sio_b9600;
+-              priv->cfg.databits  = kl5kusb105a_dtb_8;
+-              priv->cfg.unknown1  = 0;
+-              priv->cfg.unknown2  = 1;
++      priv = kmalloc(sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
+-              priv->line_state    = 0;
++      /* set initial values for control structures */
++      priv->cfg.pktlen    = 5;
++      priv->cfg.baudrate  = kl5kusb105a_sio_b9600;
++      priv->cfg.databits  = kl5kusb105a_dtb_8;
++      priv->cfg.unknown1  = 0;
++      priv->cfg.unknown2  = 1;
+-              usb_set_serial_port_data(serial->port[i], priv);
++      priv->line_state    = 0;
+-              spin_lock_init(&priv->lock);
++      spin_lock_init(&priv->lock);
+-              /* priv->termios is left uninitialized until port opening */
+-              init_waitqueue_head(&serial->port[i]->write_wait);
+-      }
++      /* priv->termios is left uninitialized until port opening */
+-      return 0;
++      usb_set_serial_port_data(port, priv);
+-err_cleanup:
+-      for (; 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;
++      return 0;
+ }
+-static void klsi_105_release(struct usb_serial *serial)
++static int klsi_105_port_remove(struct usb_serial_port *port)
+ {
+-      int i;
++      struct klsi_105_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;
+ }
+ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
diff --git a/queue-3.6/usb-spcp8x5-fix-port-data-memory-leak.patch b/queue-3.6/usb-spcp8x5-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..ceadf0e
--- /dev/null
@@ -0,0 +1,104 @@
+From bf90ff5f3b8f67e5b42df4ea4fd543f8010a2676 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 17 Oct 2012 16:31:33 +0200
+Subject: USB: spcp8x5: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit bf90ff5f3b8f67e5b42df4ea4fd543f8010a2676 upstream.
+
+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.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/spcp8x5.c |   48 +++++++++++++++++--------------------------
+ 1 file changed, 19 insertions(+), 29 deletions(-)
+
+--- a/drivers/usb/serial/spcp8x5.c
++++ b/drivers/usb/serial/spcp8x5.c
+@@ -159,13 +159,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);
+@@ -182,34 +179,27 @@ static int spcp8x5_startup(struct usb_se
+               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;
+-
+-              spin_lock_init(&priv->lock);
+-              init_waitqueue_head(&priv->delta_msr_wait);
+-              priv->type = type;
+-              usb_set_serial_port_data(serial->port[i] , priv);
+-      }
++      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(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.
+@@ -651,8 +641,8 @@ static struct usb_serial_driver spcp8x5_
+       .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,
+ };
diff --git a/queue-3.6/usb-ti_usb_3410_5052-fix-port-data-memory-leak.patch b/queue-3.6/usb-ti_usb_3410_5052-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..6e64e7f
--- /dev/null
@@ -0,0 +1,168 @@
+From 51ef847df74632e7cfdf952afc3887de105b8b35 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 17 Oct 2012 16:31:35 +0200
+Subject: USB: ti_usb_3410_5052: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 51ef847df74632e7cfdf952afc3887de105b8b35 upstream.
+
+Fix port-data memory leak by moving port data allocation and
+deallocation to 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.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ti_usb_3410_5052.c |   88 ++++++++++++++++------------------
+ 1 file changed, 43 insertions(+), 45 deletions(-)
+
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -98,6 +98,8 @@ struct ti_device {
+ static int ti_startup(struct usb_serial *serial);
+ static void ti_release(struct usb_serial *serial);
++static int ti_port_probe(struct usb_serial_port *port);
++static int ti_port_remove(struct usb_serial_port *port);
+ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port);
+ static void ti_close(struct usb_serial_port *port);
+ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
+@@ -223,6 +225,8 @@ static struct usb_serial_driver ti_1port
+       .num_ports              = 1,
+       .attach                 = ti_startup,
+       .release                = ti_release,
++      .port_probe             = ti_port_probe,
++      .port_remove            = ti_port_remove,
+       .open                   = ti_open,
+       .close                  = ti_close,
+       .write                  = ti_write,
+@@ -251,6 +255,8 @@ static struct usb_serial_driver ti_2port
+       .num_ports              = 2,
+       .attach                 = ti_startup,
+       .release                = ti_release,
++      .port_probe             = ti_port_probe,
++      .port_remove            = ti_port_remove,
+       .open                   = ti_open,
+       .close                  = ti_close,
+       .write                  = ti_write,
+@@ -358,11 +364,8 @@ module_exit(ti_exit);
+ static int ti_startup(struct usb_serial *serial)
+ {
+       struct ti_device *tdev;
+-      struct ti_port *tport;
+       struct usb_device *dev = serial->dev;
+       int status;
+-      int i;
+-
+       dbg("%s - product 0x%4X, num configurations %d, configuration value %d",
+           __func__, le16_to_cpu(dev->descriptor.idProduct),
+@@ -409,42 +412,8 @@ static int ti_startup(struct usb_serial
+               goto free_tdev;
+       }
+-      /* set up port structures */
+-      for (i = 0; i < serial->num_ports; ++i) {
+-              tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
+-              if (tport == NULL) {
+-                      dev_err(&dev->dev, "%s - out of memory\n", __func__);
+-                      status = -ENOMEM;
+-                      goto free_tports;
+-              }
+-              spin_lock_init(&tport->tp_lock);
+-              tport->tp_uart_base_addr = (i == 0 ?
+-                              TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
+-              tport->tp_closing_wait = closing_wait;
+-              init_waitqueue_head(&tport->tp_msr_wait);
+-              init_waitqueue_head(&tport->tp_write_wait);
+-              if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
+-                                                              GFP_KERNEL)) {
+-                      dev_err(&dev->dev, "%s - out of memory\n", __func__);
+-                      kfree(tport);
+-                      status = -ENOMEM;
+-                      goto free_tports;
+-              }
+-              tport->tp_port = serial->port[i];
+-              tport->tp_tdev = tdev;
+-              usb_set_serial_port_data(serial->port[i], tport);
+-              tport->tp_uart_mode = 0;        /* default is RS232 */
+-      }
+-
+       return 0;
+-free_tports:
+-      for (--i; i >= 0; --i) {
+-              tport = usb_get_serial_port_data(serial->port[i]);
+-              kfifo_free(&tport->write_fifo);
+-              kfree(tport);
+-              usb_set_serial_port_data(serial->port[i], NULL);
+-      }
+ free_tdev:
+       kfree(tdev);
+       usb_set_serial_data(serial, NULL);
+@@ -454,21 +423,50 @@ free_tdev:
+ static void ti_release(struct usb_serial *serial)
+ {
+-      int i;
+       struct ti_device *tdev = usb_get_serial_data(serial);
++
++      kfree(tdev);
++}
++
++static int ti_port_probe(struct usb_serial_port *port)
++{
+       struct ti_port *tport;
+-      for (i = 0; i < serial->num_ports; ++i) {
+-              tport = usb_get_serial_port_data(serial->port[i]);
+-              if (tport) {
+-                      kfifo_free(&tport->write_fifo);
+-                      kfree(tport);
+-              }
++      tport = kzalloc(sizeof(*tport), GFP_KERNEL);
++      if (!tport)
++              return -ENOMEM;
++
++      spin_lock_init(&tport->tp_lock);
++      if (port == port->serial->port[0])
++              tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
++      else
++              tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
++      tport->tp_closing_wait = closing_wait;
++      init_waitqueue_head(&tport->tp_msr_wait);
++      init_waitqueue_head(&tport->tp_write_wait);
++      if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
++              kfree(tport);
++              return -ENOMEM;
+       }
++      tport->tp_port = port;
++      tport->tp_tdev = usb_get_serial_data(port->serial);
++      tport->tp_uart_mode = 0;        /* default is RS232 */
+-      kfree(tdev);
++      usb_set_serial_port_data(port, tport);
++
++      return 0;
+ }
++static int ti_port_remove(struct usb_serial_port *port)
++{
++      struct ti_port *tport;
++
++      tport = usb_get_serial_port_data(port);
++      kfifo_free(&tport->write_fifo);
++      kfree(tport);
++
++      return 0;
++}
+ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
+ {