]> 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:40:25 +0000 (10:40 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 Oct 2012 17:40:25 +0000 (10:40 -0700)
added patches:
usb-ark3116-fix-null-pointer-dereference.patch
usb-belkin_sa-fix-port-data-memory-leak.patch
usb-cypress_m8-fix-port-data-memory-leak.patch
usb-f81232-fix-port-data-memory-leak.patch
usb-kobil_sct-fix-port-data-memory-leak.patch
usb-oti6858-fix-port-data-memory-leak.patch
usb-pl2303-fix-port-data-memory-leak.patch
usb-ssu100-fix-port-data-memory-leak.patch

queue-3.6/series
queue-3.6/usb-ark3116-fix-null-pointer-dereference.patch [new file with mode: 0644]
queue-3.6/usb-belkin_sa-fix-port-data-memory-leak.patch [new file with mode: 0644]
queue-3.6/usb-cypress_m8-fix-port-data-memory-leak.patch [new file with mode: 0644]
queue-3.6/usb-f81232-fix-port-data-memory-leak.patch [new file with mode: 0644]
queue-3.6/usb-kobil_sct-fix-port-data-memory-leak.patch [new file with mode: 0644]
queue-3.6/usb-oti6858-fix-port-data-memory-leak.patch [new file with mode: 0644]
queue-3.6/usb-pl2303-fix-port-data-memory-leak.patch [new file with mode: 0644]
queue-3.6/usb-ssu100-fix-port-data-memory-leak.patch [new file with mode: 0644]

index 078db074642539c90f2d9876c02cabd7d425059d..b489a547e1b61d3d11a36187f2881adf86b22683 100644 (file)
@@ -26,3 +26,11 @@ usb-musb-am35xx-drop-spurious-unplugging-a-device.patch
 usb-host-xhci-new-system-added-for-compliance-mode-patch-on-sn65lvpe502cp.patch
 usb-iuu_phoenix-fix-port-data-memory-leak.patch
 usb-iuu_phoenix-fix-sysfs-attribute-creation.patch
+usb-ark3116-fix-null-pointer-dereference.patch
+usb-f81232-fix-port-data-memory-leak.patch
+usb-oti6858-fix-port-data-memory-leak.patch
+usb-belkin_sa-fix-port-data-memory-leak.patch
+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
diff --git a/queue-3.6/usb-ark3116-fix-null-pointer-dereference.patch b/queue-3.6/usb-ark3116-fix-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..65e1790
--- /dev/null
@@ -0,0 +1,86 @@
+From 7bdce71822f471433dd3014692e9096996c7b5f0 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 15 Oct 2012 18:20:52 +0200
+Subject: USB: ark3116: fix NULL-pointer dereference
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 7bdce71822f471433dd3014692e9096996c7b5f0 upstream.
+
+Fix NULL-pointer dereference at release 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 NULL when release is called.
+
+Compile-only tested.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ark3116.c |   26 ++++++++++++++------------
+ 1 file changed, 14 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/serial/ark3116.c
++++ b/drivers/usb/serial/ark3116.c
+@@ -126,9 +126,6 @@ static inline int calc_divisor(int bps)
+ static int ark3116_attach(struct usb_serial *serial)
+ {
+-      struct usb_serial_port *port = serial->port[0];
+-      struct ark3116_private *priv;
+-
+       /* make sure we have our end-points */
+       if ((serial->num_bulk_in == 0) ||
+           (serial->num_bulk_out == 0) ||
+@@ -143,8 +140,15 @@ static int ark3116_attach(struct usb_ser
+               return -EINVAL;
+       }
+-      priv = kzalloc(sizeof(struct ark3116_private),
+-                     GFP_KERNEL);
++      return 0;
++}
++
++static int ark3116_port_probe(struct usb_serial_port *port)
++{
++      struct usb_serial *serial = port->serial;
++      struct ark3116_private *priv;
++
++      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+@@ -199,18 +203,15 @@ static int ark3116_attach(struct usb_ser
+       return 0;
+ }
+-static void ark3116_release(struct usb_serial *serial)
++static int ark3116_port_remove(struct usb_serial_port *port)
+ {
+-      struct usb_serial_port *port = serial->port[0];
+       struct ark3116_private *priv = usb_get_serial_port_data(port);
+       /* device is closed, so URBs and DMA should be down */
+-
+-      usb_set_serial_port_data(port, NULL);
+-
+       mutex_destroy(&priv->hw_lock);
+-
+       kfree(priv);
++
++      return 0;
+ }
+ static void ark3116_init_termios(struct tty_struct *tty)
+@@ -725,7 +726,8 @@ static struct usb_serial_driver ark3116_
+       .id_table =             id_table,
+       .num_ports =            1,
+       .attach =               ark3116_attach,
+-      .release =              ark3116_release,
++      .port_probe =           ark3116_port_probe,
++      .port_remove =          ark3116_port_remove,
+       .set_termios =          ark3116_set_termios,
+       .init_termios =         ark3116_init_termios,
+       .ioctl =                ark3116_ioctl,
diff --git a/queue-3.6/usb-belkin_sa-fix-port-data-memory-leak.patch b/queue-3.6/usb-belkin_sa-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..8fc4063
--- /dev/null
@@ -0,0 +1,99 @@
+From fa919751a2d26a88140fc5810124dd81644efe51 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 15 Oct 2012 18:20:53 +0200
+Subject: USB: belkin_sa: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit fa919751a2d26a88140fc5810124dd81644efe51 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/belkin_sa.c |   31 +++++++++++++++----------------
+ 1 file changed, 15 insertions(+), 16 deletions(-)
+
+--- a/drivers/usb/serial/belkin_sa.c
++++ b/drivers/usb/serial/belkin_sa.c
+@@ -47,8 +47,8 @@ static bool debug;
+ #define DRIVER_DESC "USB Belkin Serial converter driver"
+ /* function prototypes for a Belkin USB Serial Adapter F5U103 */
+-static int  belkin_sa_startup(struct usb_serial *serial);
+-static void belkin_sa_release(struct usb_serial *serial);
++static int belkin_sa_port_probe(struct usb_serial_port *port);
++static int belkin_sa_port_remove(struct usb_serial_port *port);
+ static int  belkin_sa_open(struct tty_struct *tty,
+                       struct usb_serial_port *port);
+ static void belkin_sa_close(struct usb_serial_port *port);
+@@ -90,8 +90,8 @@ static struct usb_serial_driver belkin_d
+       .break_ctl =            belkin_sa_break_ctl,
+       .tiocmget =             belkin_sa_tiocmget,
+       .tiocmset =             belkin_sa_tiocmset,
+-      .attach =               belkin_sa_startup,
+-      .release =              belkin_sa_release,
++      .port_probe =           belkin_sa_port_probe,
++      .port_remove =          belkin_sa_port_remove,
+ };
+ static struct usb_serial_driver * const serial_drivers[] = {
+@@ -120,17 +120,15 @@ struct belkin_sa_private {
+                                           (c), BELKIN_SA_SET_REQUEST_TYPE, \
+                                           (v), 0, NULL, 0, WDR_TIMEOUT)
+-/* do some startup allocations not currently performed by usb_serial_probe() */
+-static int belkin_sa_startup(struct usb_serial *serial)
++static int belkin_sa_port_probe(struct usb_serial_port *port)
+ {
+-      struct usb_device *dev = serial->dev;
++      struct usb_device *dev = port->serial->dev;
+       struct belkin_sa_private *priv;
+-      /* allocate the private data structure */
+       priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
+       if (!priv)
+-              return -1; /* error */
+-      /* set initial values for control structures */
++              return -ENOMEM;
++
+       spin_lock_init(&priv->lock);
+       priv->control_state = 0;
+       priv->last_lsr = 0;
+@@ -142,18 +140,19 @@ static int belkin_sa_startup(struct usb_
+                                       le16_to_cpu(dev->descriptor.bcdDevice),
+                                       priv->bad_flow_control);
+-      init_waitqueue_head(&serial->port[0]->write_wait);
+-      usb_set_serial_port_data(serial->port[0], priv);
++      usb_set_serial_port_data(port, priv);
+       return 0;
+ }
+-static void belkin_sa_release(struct usb_serial *serial)
++static int belkin_sa_port_remove(struct usb_serial_port *port)
+ {
+-      int i;
++      struct belkin_sa_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 belkin_sa_open(struct tty_struct *tty,
diff --git a/queue-3.6/usb-cypress_m8-fix-port-data-memory-leak.patch b/queue-3.6/usb-cypress_m8-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..c19661f
--- /dev/null
@@ -0,0 +1,188 @@
+From 5c1a0f418d8d985f3a62849bcac43fc5404cc592 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 17 Oct 2012 13:34:55 +0200
+Subject: USB: cypress_m8: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 5c1a0f418d8d985f3a62849bcac43fc5404cc592 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/cypress_m8.c |   82 ++++++++++++++++++++--------------------
+ 1 file changed, 41 insertions(+), 41 deletions(-)
+
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -124,10 +124,10 @@ struct cypress_private {
+ };
+ /* function prototypes for the Cypress USB to serial device */
+-static int  cypress_earthmate_startup(struct usb_serial *serial);
+-static int  cypress_hidcom_startup(struct usb_serial *serial);
+-static int  cypress_ca42v2_startup(struct usb_serial *serial);
+-static void cypress_release(struct usb_serial *serial);
++static int  cypress_earthmate_port_probe(struct usb_serial_port *port);
++static int  cypress_hidcom_port_probe(struct usb_serial_port *port);
++static int  cypress_ca42v2_port_probe(struct usb_serial_port *port);
++static int  cypress_port_remove(struct usb_serial_port *port);
+ static int  cypress_open(struct tty_struct *tty, struct usb_serial_port *port);
+ static void cypress_close(struct usb_serial_port *port);
+ static void cypress_dtr_rts(struct usb_serial_port *port, int on);
+@@ -157,8 +157,8 @@ static struct usb_serial_driver cypress_
+       .description =                  "DeLorme Earthmate USB",
+       .id_table =                     id_table_earthmate,
+       .num_ports =                    1,
+-      .attach =                       cypress_earthmate_startup,
+-      .release =                      cypress_release,
++      .port_probe =                   cypress_earthmate_port_probe,
++      .port_remove =                  cypress_port_remove,
+       .open =                         cypress_open,
+       .close =                        cypress_close,
+       .dtr_rts =                      cypress_dtr_rts,
+@@ -183,8 +183,8 @@ static struct usb_serial_driver cypress_
+       .description =                  "HID->COM RS232 Adapter",
+       .id_table =                     id_table_cyphidcomrs232,
+       .num_ports =                    1,
+-      .attach =                       cypress_hidcom_startup,
+-      .release =                      cypress_release,
++      .port_probe =                   cypress_hidcom_port_probe,
++      .port_remove =                  cypress_port_remove,
+       .open =                         cypress_open,
+       .close =                        cypress_close,
+       .dtr_rts =                      cypress_dtr_rts,
+@@ -209,8 +209,8 @@ static struct usb_serial_driver cypress_
+       .description =                  "Nokia CA-42 V2 Adapter",
+       .id_table =                     id_table_nokiaca42v2,
+       .num_ports =                    1,
+-      .attach =                       cypress_ca42v2_startup,
+-      .release =                      cypress_release,
++      .port_probe =                   cypress_ca42v2_port_probe,
++      .port_remove =                  cypress_port_remove,
+       .open =                         cypress_open,
+       .close =                        cypress_close,
+       .dtr_rts =                      cypress_dtr_rts,
+@@ -437,10 +437,10 @@ static void cypress_set_dead(struct usb_
+  *****************************************************************************/
+-static int generic_startup(struct usb_serial *serial)
++static int cypress_generic_port_probe(struct usb_serial_port *port)
+ {
++      struct usb_serial *serial = port->serial;
+       struct cypress_private *priv;
+-      struct usb_serial_port *port = serial->port[0];
+       priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
+       if (!priv)
+@@ -489,15 +489,17 @@ static int generic_startup(struct usb_se
+ }
+-static int cypress_earthmate_startup(struct usb_serial *serial)
++static int cypress_earthmate_port_probe(struct usb_serial_port *port)
+ {
++      struct usb_serial *serial = port->serial;
+       struct cypress_private *priv;
+-      struct usb_serial_port *port = serial->port[0];
++      int ret;
+-      if (generic_startup(serial)) {
++      ret = cypress_generic_port_probe(port);
++      if (ret) {
+               dbg("%s - Failed setting up port %d", __func__,
+                               port->number);
+-              return 1;
++              return ret;
+       }
+       priv = usb_get_serial_port_data(port);
+@@ -517,54 +519,52 @@ static int cypress_earthmate_startup(str
+       }
+       return 0;
+-} /* cypress_earthmate_startup */
+-
++}
+-static int cypress_hidcom_startup(struct usb_serial *serial)
++static int cypress_hidcom_port_probe(struct usb_serial_port *port)
+ {
+       struct cypress_private *priv;
++      int ret;
+-      if (generic_startup(serial)) {
+-              dbg("%s - Failed setting up port %d", __func__,
+-                              serial->port[0]->number);
+-              return 1;
++      ret = cypress_generic_port_probe(port);
++      if (ret) {
++              dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
++              return ret;
+       }
+-      priv = usb_get_serial_port_data(serial->port[0]);
++      priv = usb_get_serial_port_data(port);
+       priv->chiptype = CT_CYPHIDCOM;
+       return 0;
+-} /* cypress_hidcom_startup */
+-
++}
+-static int cypress_ca42v2_startup(struct usb_serial *serial)
++static int cypress_ca42v2_port_probe(struct usb_serial_port *port)
+ {
+       struct cypress_private *priv;
++      int ret;
+-      if (generic_startup(serial)) {
+-              dbg("%s - Failed setting up port %d", __func__,
+-                              serial->port[0]->number);
+-              return 1;
++      ret = cypress_generic_port_probe(port);
++      if (ret) {
++              dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
++              return ret;
+       }
+-      priv = usb_get_serial_port_data(serial->port[0]);
++      priv = usb_get_serial_port_data(port);
+       priv->chiptype = CT_CA42V2;
+       return 0;
+-} /* cypress_ca42v2_startup */
+-
++}
+-static void cypress_release(struct usb_serial *serial)
++static int cypress_port_remove(struct usb_serial_port *port)
+ {
+       struct cypress_private *priv;
+-      /* all open ports are closed at this point */
+-      priv = usb_get_serial_port_data(serial->port[0]);
++      priv = usb_get_serial_port_data(port);
+-      if (priv) {
+-              kfifo_free(&priv->write_fifo);
+-              kfree(priv);
+-      }
++      kfifo_free(&priv->write_fifo);
++      kfree(priv);
++
++      return 0;
+ }
diff --git a/queue-3.6/usb-f81232-fix-port-data-memory-leak.patch b/queue-3.6/usb-f81232-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..d451fa3
--- /dev/null
@@ -0,0 +1,93 @@
+From 3124d1d71d3df59d40b913b5481df58099e811d1 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 17 Oct 2012 13:34:56 +0200
+Subject: USB: f81232: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 3124d1d71d3df59d40b913b5481df58099e811d1 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/f81232.c |   43 +++++++++++++++++--------------------------
+ 1 file changed, 17 insertions(+), 26 deletions(-)
+
+--- a/drivers/usb/serial/f81232.c
++++ b/drivers/usb/serial/f81232.c
+@@ -319,39 +319,30 @@ static int f81232_ioctl(struct tty_struc
+       return -ENOIOCTLCMD;
+ }
+-static int f81232_startup(struct usb_serial *serial)
++static int f81232_port_probe(struct usb_serial_port *port)
+ {
+       struct f81232_private *priv;
+-      int i;
+-      for (i = 0; i < serial->num_ports; ++i) {
+-              priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL);
+-              if (!priv)
+-                      goto cleanup;
+-              spin_lock_init(&priv->lock);
+-              init_waitqueue_head(&priv->delta_msr_wait);
+-              usb_set_serial_port_data(serial->port[i], priv);
+-      }
+-      return 0;
++      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      spin_lock_init(&priv->lock);
++      init_waitqueue_head(&priv->delta_msr_wait);
++
++      usb_set_serial_port_data(port, priv);
+-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;
++      return 0;
+ }
+-static void f81232_release(struct usb_serial *serial)
++static int f81232_port_remove(struct usb_serial_port *port)
+ {
+-      int i;
+       struct f81232_private *priv;
+-      for (i = 0; i < serial->num_ports; ++i) {
+-              priv = usb_get_serial_port_data(serial->port[i]);
+-              kfree(priv);
+-      }
++      priv = usb_get_serial_port_data(port);
++      kfree(priv);
++
++      return 0;
+ }
+ static struct usb_serial_driver f81232_device = {
+@@ -374,8 +365,8 @@ static struct usb_serial_driver f81232_d
+       .tiocmset =             f81232_tiocmset,
+       .process_read_urb =     f81232_process_read_urb,
+       .read_int_callback =    f81232_read_int_callback,
+-      .attach =               f81232_startup,
+-      .release =              f81232_release,
++      .port_probe =           f81232_port_probe,
++      .port_remove =          f81232_port_remove,
+ };
+ static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/queue-3.6/usb-kobil_sct-fix-port-data-memory-leak.patch b/queue-3.6/usb-kobil_sct-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..d130bb4
--- /dev/null
@@ -0,0 +1,89 @@
+From 95940a04bfe8a4d246f4ca17c6a3b00148bdead0 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 17 Oct 2012 13:35:02 +0200
+Subject: USB: kobil_sct: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 95940a04bfe8a4d246f4ca17c6a3b00148bdead0 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/kobil_sct.c |   23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/serial/kobil_sct.c
++++ b/drivers/usb/serial/kobil_sct.c
+@@ -56,8 +56,8 @@ static bool debug;
+ /* Function prototypes */
+-static int  kobil_startup(struct usb_serial *serial);
+-static void kobil_release(struct usb_serial *serial);
++static int kobil_port_probe(struct usb_serial_port *probe);
++static int kobil_port_remove(struct usb_serial_port *probe);
+ static int  kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
+ static void kobil_close(struct usb_serial_port *port);
+ static int  kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
+@@ -91,8 +91,8 @@ static struct usb_serial_driver kobil_de
+       .description =          "KOBIL USB smart card terminal",
+       .id_table =             id_table,
+       .num_ports =            1,
+-      .attach =               kobil_startup,
+-      .release =              kobil_release,
++      .port_probe =           kobil_port_probe,
++      .port_remove =          kobil_port_remove,
+       .ioctl =                kobil_ioctl,
+       .set_termios =          kobil_set_termios,
+       .init_termios =         kobil_init_termios,
+@@ -119,9 +119,10 @@ struct kobil_private {
+ };
+-static int kobil_startup(struct usb_serial *serial)
++static int kobil_port_probe(struct usb_serial_port *port)
+ {
+       int i;
++      struct usb_serial *serial = port->serial;
+       struct kobil_private *priv;
+       struct usb_device *pdev;
+       struct usb_host_config *actconfig;
+@@ -152,7 +153,7 @@ static int kobil_startup(struct usb_seri
+               printk(KERN_DEBUG "KOBIL KAAN SIM detected\n");
+               break;
+       }
+-      usb_set_serial_port_data(serial->port[0], priv);
++      usb_set_serial_port_data(port, priv);
+       /* search for the necessary endpoints */
+       pdev = serial->dev;
+@@ -180,12 +181,14 @@ static int kobil_startup(struct usb_seri
+ }
+-static void kobil_release(struct usb_serial *serial)
++static int kobil_port_remove(struct usb_serial_port *port)
+ {
+-      int i;
++      struct kobil_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 void kobil_init_termios(struct tty_struct *tty)
diff --git a/queue-3.6/usb-oti6858-fix-port-data-memory-leak.patch b/queue-3.6/usb-oti6858-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..e5b600c
--- /dev/null
@@ -0,0 +1,126 @@
+From 289b076f89c2c3260e914dad18ae12f193ea86d5 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 17 Oct 2012 16:31:32 +0200
+Subject: USB: oti6858: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 289b076f89c2c3260e914dad18ae12f193ea86d5 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/oti6858.c |   68 +++++++++++++++++--------------------------
+ 1 file changed, 28 insertions(+), 40 deletions(-)
+
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -139,8 +139,8 @@ static int oti6858_chars_in_buffer(struc
+ static int oti6858_tiocmget(struct tty_struct *tty);
+ static int oti6858_tiocmset(struct tty_struct *tty,
+                               unsigned int set, unsigned int clear);
+-static int oti6858_startup(struct usb_serial *serial);
+-static void oti6858_release(struct usb_serial *serial);
++static int oti6858_port_probe(struct usb_serial_port *port);
++static int oti6858_port_remove(struct usb_serial_port *port);
+ /* device info */
+ static struct usb_serial_driver oti6858_device = {
+@@ -163,8 +163,8 @@ static struct usb_serial_driver oti6858_
+       .write_bulk_callback =  oti6858_write_bulk_callback,
+       .write_room =           oti6858_write_room,
+       .chars_in_buffer =      oti6858_chars_in_buffer,
+-      .attach =               oti6858_startup,
+-      .release =              oti6858_release,
++      .port_probe =           oti6858_port_probe,
++      .port_remove =          oti6858_port_remove,
+ };
+ static struct usb_serial_driver * const serial_drivers[] = {
+@@ -333,36 +333,33 @@ static void send_data(struct work_struct
+       usb_serial_port_softint(port);
+ }
+-static int oti6858_startup(struct usb_serial *serial)
++static int oti6858_port_probe(struct usb_serial_port *port)
+ {
+-      struct usb_serial_port *port = serial->port[0];
+       struct oti6858_private *priv;
+-      int i;
+-      for (i = 0; i < serial->num_ports; ++i) {
+-              priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
+-              if (!priv)
+-                      break;
+-
+-              spin_lock_init(&priv->lock);
+-              init_waitqueue_head(&priv->intr_wait);
+-/*            INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
+-/*            INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
+-              priv->port = port;
+-              INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
+-              INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
+-
+-              usb_set_serial_port_data(serial->port[i], priv);
+-      }
+-      if (i == serial->num_ports)
+-              return 0;
+-
+-      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;
++      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      spin_lock_init(&priv->lock);
++      init_waitqueue_head(&priv->intr_wait);
++      priv->port = port;
++      INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
++      INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
++
++      usb_set_serial_port_data(port, priv);
++
++      return 0;
++}
++
++static int oti6858_port_remove(struct usb_serial_port *port)
++{
++      struct oti6858_private *priv;
++
++      priv = usb_get_serial_port_data(port);
++      kfree(priv);
++
++      return 0;
+ }
+ static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
+@@ -714,15 +711,6 @@ static int oti6858_ioctl(struct tty_stru
+       return -ENOIOCTLCMD;
+ }
+-
+-static void oti6858_release(struct usb_serial *serial)
+-{
+-      int i;
+-
+-      for (i = 0; i < serial->num_ports; ++i)
+-              kfree(usb_get_serial_port_data(serial->port[i]));
+-}
+-
+ static void oti6858_read_int_callback(struct urb *urb)
+ {
+       struct usb_serial_port *port =  urb->context;
diff --git a/queue-3.6/usb-pl2303-fix-port-data-memory-leak.patch b/queue-3.6/usb-pl2303-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..4f03558
--- /dev/null
@@ -0,0 +1,199 @@
+From 8bf769eb5f6efc33f95088850f33fcc05d28b508 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 15 Oct 2012 15:47:21 +0200
+Subject: USB: pl2303: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 8bf769eb5f6efc33f95088850f33fcc05d28b508 upstream.
+
+Fix port-data memory leak by allocating and freeing port data in
+port_probe/remove rather than in attach/release, and by introducing
+serial private data to store the device type which is interface rather
+than port specific.
+
+Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no
+driver is bound) the port private data is no longer freed at release.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/pl2303.c |   90 ++++++++++++++++++++++++++------------------
+ 1 file changed, 54 insertions(+), 36 deletions(-)
+
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -135,12 +135,15 @@ enum pl2303_type {
+       HX,             /* HX version of the pl2303 chip */
+ };
++struct pl2303_serial_private {
++      enum pl2303_type type;
++};
++
+ struct pl2303_private {
+       spinlock_t lock;
+       wait_queue_head_t delta_msr_wait;
+       u8 line_control;
+       u8 line_status;
+-      enum pl2303_type type;
+ };
+ static int pl2303_vendor_read(__u16 value, __u16 index,
+@@ -169,14 +172,19 @@ static int pl2303_vendor_write(__u16 val
+ static int pl2303_startup(struct usb_serial *serial)
+ {
+-      struct pl2303_private *priv;
++      struct pl2303_serial_private *spriv;
+       enum pl2303_type type = type_0;
+       unsigned char *buf;
+-      int i;
++
++      spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
++      if (!spriv)
++              return -ENOMEM;
+       buf = kmalloc(10, GFP_KERNEL);
+-      if (buf == NULL)
++      if (!buf) {
++              kfree(spriv);
+               return -ENOMEM;
++      }
+       if (serial->dev->descriptor.bDeviceClass == 0x02)
+               type = type_0;
+@@ -188,15 +196,8 @@ static int pl2303_startup(struct usb_ser
+               type = type_1;
+       dev_dbg(&serial->interface->dev, "device type: %d\n", type);
+-      for (i = 0; i < serial->num_ports; ++i) {
+-              priv = kzalloc(sizeof(struct pl2303_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);
+-      }
++      spriv->type = type;
++      usb_set_serial_data(serial, spriv);
+       pl2303_vendor_read(0x8484, 0, serial, buf);
+       pl2303_vendor_write(0x0404, 0, serial);
+@@ -215,15 +216,40 @@ static int pl2303_startup(struct usb_ser
+       kfree(buf);
+       return 0;
++}
+-cleanup:
+-      kfree(buf);
+-      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;
++static void pl2303_release(struct usb_serial *serial)
++{
++      struct pl2303_serial_private *spriv;
++
++      spriv = usb_get_serial_data(serial);
++      kfree(spriv);
++}
++
++static int pl2303_port_probe(struct usb_serial_port *port)
++{
++      struct pl2303_private *priv;
++
++      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      spin_lock_init(&priv->lock);
++      init_waitqueue_head(&priv->delta_msr_wait);
++
++      usb_set_serial_port_data(port, priv);
++
++      return 0;
++}
++
++static int pl2303_port_remove(struct usb_serial_port *port)
++{
++      struct pl2303_private *priv;
++
++      priv = usb_get_serial_port_data(port);
++      kfree(priv);
++
++      return 0;
+ }
+ static int set_control_lines(struct usb_device *dev, u8 value)
+@@ -242,6 +268,7 @@ static void pl2303_set_termios(struct tt
+               struct usb_serial_port *port, struct ktermios *old_termios)
+ {
+       struct usb_serial *serial = port->serial;
++      struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int cflag;
+@@ -325,7 +352,7 @@ static void pl2303_set_termios(struct tt
+               }
+               if (baud > 1228800) {
+                       /* type_0, type_1 only support up to 1228800 baud */
+-                      if (priv->type != HX)
++                      if (spriv->type != HX)
+                               baud = 1228800;
+                       else if (baud > 6000000)
+                               baud = 6000000;
+@@ -428,7 +455,7 @@ static void pl2303_set_termios(struct tt
+            buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+       if (cflag & CRTSCTS) {
+-              if (priv->type == HX)
++              if (spriv->type == HX)
+                       pl2303_vendor_write(0x0, 0x61, serial);
+               else
+                       pl2303_vendor_write(0x0, 0x41, serial);
+@@ -470,10 +497,10 @@ static int pl2303_open(struct tty_struct
+ {
+       struct ktermios tmp_termios;
+       struct usb_serial *serial = port->serial;
+-      struct pl2303_private *priv = usb_get_serial_port_data(port);
++      struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
+       int result;
+-      if (priv->type != HX) {
++      if (spriv->type != HX) {
+               usb_clear_halt(serial->dev, port->write_urb->pipe);
+               usb_clear_halt(serial->dev, port->read_urb->pipe);
+       } else {
+@@ -657,17 +684,6 @@ static void pl2303_break_ctl(struct tty_
+               dev_err(&port->dev, "error sending break = %d\n", result);
+ }
+-static void pl2303_release(struct usb_serial *serial)
+-{
+-      int i;
+-      struct pl2303_private *priv;
+-
+-      for (i = 0; i < serial->num_ports; ++i) {
+-              priv = usb_get_serial_port_data(serial->port[i]);
+-              kfree(priv);
+-      }
+-}
+-
+ static void pl2303_update_line_status(struct usb_serial_port *port,
+                                     unsigned char *data,
+                                     unsigned int actual_length)
+@@ -829,6 +845,8 @@ static struct usb_serial_driver pl2303_d
+       .read_int_callback =    pl2303_read_int_callback,
+       .attach =               pl2303_startup,
+       .release =              pl2303_release,
++      .port_probe =           pl2303_port_probe,
++      .port_remove =          pl2303_port_remove,
+ };
+ static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/queue-3.6/usb-ssu100-fix-port-data-memory-leak.patch b/queue-3.6/usb-ssu100-fix-port-data-memory-leak.patch
new file mode 100644 (file)
index 0000000..9811163
--- /dev/null
@@ -0,0 +1,91 @@
+From 638b9e15233c9570bce65301aa9877235316b9f0 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Wed, 17 Oct 2012 16:31:34 +0200
+Subject: USB: ssu100: fix port-data memory leak
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 638b9e15233c9570bce65301aa9877235316b9f0 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/ssu100.c |   34 ++++++++++++++++++++--------------
+ 1 file changed, 20 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -69,13 +69,6 @@ struct ssu100_port_private {
+       struct async_icount icount;
+ };
+-static void ssu100_release(struct usb_serial *serial)
+-{
+-      struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port);
+-
+-      kfree(priv);
+-}
+-
+ static inline int ssu100_control_msg(struct usb_device *dev,
+                                    u8 request, u16 data, u16 index)
+ {
+@@ -444,21 +437,33 @@ static int ssu100_ioctl(struct tty_struc
+ static int ssu100_attach(struct usb_serial *serial)
+ {
++      return ssu100_initdevice(serial->dev);
++}
++
++static int ssu100_port_probe(struct usb_serial_port *port)
++{
+       struct ssu100_port_private *priv;
+-      struct usb_serial_port *port = *serial->port;
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+-      if (!priv) {
+-              dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
+-                      sizeof(*priv));
++      if (!priv)
+               return -ENOMEM;
+-      }
+       spin_lock_init(&priv->status_lock);
+       init_waitqueue_head(&priv->delta_msr_wait);
++
+       usb_set_serial_port_data(port, priv);
+-      return ssu100_initdevice(serial->dev);
++      return 0;
++}
++
++static int ssu100_port_remove(struct usb_serial_port *port)
++{
++      struct ssu100_port_private *priv;
++
++      priv = usb_get_serial_port_data(port);
++      kfree(priv);
++
++      return 0;
+ }
+ static int ssu100_tiocmget(struct tty_struct *tty)
+@@ -649,7 +654,8 @@ static struct usb_serial_driver ssu100_d
+       .open                = ssu100_open,
+       .close               = ssu100_close,
+       .attach              = ssu100_attach,
+-      .release             = ssu100_release,
++      .port_probe          = ssu100_port_probe,
++      .port_remove         = ssu100_port_remove,
+       .dtr_rts             = ssu100_dtr_rts,
+       .process_read_urb    = ssu100_process_read_urb,
+       .tiocmget            = ssu100_tiocmget,