]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.8-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 22:38:43 +0000 (15:38 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 22:38:43 +0000 (15:38 -0700)
added patches:
usb-ark3116-fix-use-after-free-in-tiocmiwait.patch
usb-ch341-fix-use-after-free-in-tiocmiwait.patch
usb-cypress_m8-fix-use-after-free-in-tiocmiwait.patch
usb-f81232-fix-use-after-free-in-tiocmiwait.patch
usb-ftdi_sio-fix-use-after-free-in-tiocmiwait.patch
usb-io_edgeport-fix-use-after-free-in-tiocmiwait.patch
usb-io_ti-fix-use-after-free-in-tiocmiwait.patch
usb-mct_u232-fix-use-after-free-in-tiocmiwait.patch
usb-mos7840-fix-broken-tiocmiwait.patch
usb-mos7840-fix-use-after-free-in-tiocmiwait.patch
usb-oti6858-fix-use-after-free-in-tiocmiwait.patch
usb-pl2303-fix-use-after-free-in-tiocmiwait.patch
usb-quatech2-fix-use-after-free-in-tiocmiwait.patch
usb-spcp8x5-fix-use-after-free-in-tiocmiwait.patch
usb-ssu100-fix-use-after-free-in-tiocmiwait.patch
usb-ti_usb_3410_5052-fix-use-after-free-in-tiocmiwait.patch

17 files changed:
queue-3.8/series
queue-3.8/usb-ark3116-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-ch341-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-cypress_m8-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-f81232-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-ftdi_sio-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-io_edgeport-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-io_ti-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-mct_u232-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-mos7840-fix-broken-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-mos7840-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-oti6858-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-pl2303-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-quatech2-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-spcp8x5-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-ssu100-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]
queue-3.8/usb-ti_usb_3410_5052-fix-use-after-free-in-tiocmiwait.patch [new file with mode: 0644]

index 1e670a9a0bf11764059755322a52176e0f96718a..51fe26aa909297de0fd278917df1cd59a6a7985c 100644 (file)
@@ -58,3 +58,19 @@ btrfs-limit-the-global-reserve-to-512mb.patch
 btrfs-don-t-drop-path-when-printing-out-tree-errors-in-scrub.patch
 usb-serial-add-modem-status-change-wait-queue.patch
 usb-serial-fix-hang-when-opening-port.patch
+usb-quatech2-fix-use-after-free-in-tiocmiwait.patch
+usb-mos7840-fix-broken-tiocmiwait.patch
+usb-io_ti-fix-use-after-free-in-tiocmiwait.patch
+usb-oti6858-fix-use-after-free-in-tiocmiwait.patch
+usb-ftdi_sio-fix-use-after-free-in-tiocmiwait.patch
+usb-pl2303-fix-use-after-free-in-tiocmiwait.patch
+usb-mos7840-fix-use-after-free-in-tiocmiwait.patch
+usb-spcp8x5-fix-use-after-free-in-tiocmiwait.patch
+usb-ssu100-fix-use-after-free-in-tiocmiwait.patch
+usb-ch341-fix-use-after-free-in-tiocmiwait.patch
+usb-io_edgeport-fix-use-after-free-in-tiocmiwait.patch
+usb-f81232-fix-use-after-free-in-tiocmiwait.patch
+usb-ark3116-fix-use-after-free-in-tiocmiwait.patch
+usb-mct_u232-fix-use-after-free-in-tiocmiwait.patch
+usb-cypress_m8-fix-use-after-free-in-tiocmiwait.patch
+usb-ti_usb_3410_5052-fix-use-after-free-in-tiocmiwait.patch
diff --git a/queue-3.8/usb-ark3116-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-ark3116-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..156f56d
--- /dev/null
@@ -0,0 +1,65 @@
+From 5018860321dc7a9e50a75d5f319bc981298fb5b7 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:11 +0100
+Subject: USB: ark3116: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 5018860321dc7a9e50a75d5f319bc981298fb5b7 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ark3116.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/serial/ark3116.c
++++ b/drivers/usb/serial/ark3116.c
+@@ -62,7 +62,6 @@ static int is_irda(struct usb_serial *se
+ }
+ struct ark3116_private {
+-      wait_queue_head_t       delta_msr_wait;
+       struct async_icount     icount;
+       int                     irda;   /* 1 for irda device */
+@@ -146,7 +145,6 @@ static int ark3116_port_probe(struct usb
+       if (!priv)
+               return -ENOMEM;
+-      init_waitqueue_head(&priv->delta_msr_wait);
+       mutex_init(&priv->hw_lock);
+       spin_lock_init(&priv->status_lock);
+@@ -456,10 +454,14 @@ static int ark3116_ioctl(struct tty_stru
+       case TIOCMIWAIT:
+               for (;;) {
+                       struct async_icount prev = priv->icount;
+-                      interruptible_sleep_on(&priv->delta_msr_wait);
++                      interruptible_sleep_on(&port->delta_msr_wait);
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
++
++                      if (port->serial->disconnected)
++                              return -EIO;
++
+                       if ((prev.rng == priv->icount.rng) &&
+                           (prev.dsr == priv->icount.dsr) &&
+                           (prev.dcd == priv->icount.dcd) &&
+@@ -580,7 +582,7 @@ static void ark3116_update_msr(struct us
+                       priv->icount.dcd++;
+               if (msr & UART_MSR_TERI)
+                       priv->icount.rng++;
+-              wake_up_interruptible(&priv->delta_msr_wait);
++              wake_up_interruptible(&port->delta_msr_wait);
+       }
+ }
diff --git a/queue-3.8/usb-ch341-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-ch341-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..e4d8101
--- /dev/null
@@ -0,0 +1,74 @@
+From fa1e11d5231c001c80a479160b5832933c5d35fb Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:12 +0100
+Subject: USB: ch341: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit fa1e11d5231c001c80a479160b5832933c5d35fb upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ch341.c |   11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/ch341.c
++++ b/drivers/usb/serial/ch341.c
+@@ -80,7 +80,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
+ struct ch341_private {
+       spinlock_t lock; /* access lock */
+-      wait_queue_head_t delta_msr_wait; /* wait queue for modem status */
+       unsigned baud_rate; /* set baud rate */
+       u8 line_control; /* set line control value RTS/DTR */
+       u8 line_status; /* active status of modem control inputs */
+@@ -252,7 +251,6 @@ static int ch341_port_probe(struct usb_s
+               return -ENOMEM;
+       spin_lock_init(&priv->lock);
+-      init_waitqueue_head(&priv->delta_msr_wait);
+       priv->baud_rate = DEFAULT_BAUD_RATE;
+       priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
+@@ -298,7 +296,7 @@ static void ch341_dtr_rts(struct usb_ser
+               priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
+       spin_unlock_irqrestore(&priv->lock, flags);
+       ch341_set_handshake(port->serial->dev, priv->line_control);
+-      wake_up_interruptible(&priv->delta_msr_wait);
++      wake_up_interruptible(&port->delta_msr_wait);
+ }
+ static void ch341_close(struct usb_serial_port *port)
+@@ -491,7 +489,7 @@ static void ch341_read_int_callback(stru
+                       tty_kref_put(tty);
+               }
+-              wake_up_interruptible(&priv->delta_msr_wait);
++              wake_up_interruptible(&port->delta_msr_wait);
+       }
+ exit:
+@@ -517,11 +515,14 @@ static int wait_modem_info(struct usb_se
+       spin_unlock_irqrestore(&priv->lock, flags);
+       while (!multi_change) {
+-              interruptible_sleep_on(&priv->delta_msr_wait);
++              interruptible_sleep_on(&port->delta_msr_wait);
+               /* see if a signal did it */
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
++              if (port->serial->disconnected)
++                      return -EIO;
++
+               spin_lock_irqsave(&priv->lock, flags);
+               status = priv->line_status;
+               multi_change = priv->multi_status_change;
diff --git a/queue-3.8/usb-cypress_m8-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-cypress_m8-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..cad00a3
--- /dev/null
@@ -0,0 +1,72 @@
+From 356050d8b1e526db093e9d2c78daf49d6bf418e3 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:13 +0100
+Subject: USB: cypress_m8: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 356050d8b1e526db093e9d2c78daf49d6bf418e3 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Also remove bogus test for private data pointer being NULL as it is
+never assigned in the loop.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/cypress_m8.c |   14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -111,7 +111,6 @@ struct cypress_private {
+       int baud_rate;                     /* stores current baud rate in
+                                             integer form */
+       int isthrottled;                   /* if throttled, discard reads */
+-      wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
+       char prev_status, diff_status;     /* used for TIOCMIWAIT */
+       /* we pass a pointer to this as the argument sent to
+          cypress_set_termios old_termios */
+@@ -449,7 +448,6 @@ static int cypress_generic_port_probe(st
+               kfree(priv);
+               return -ENOMEM;
+       }
+-      init_waitqueue_head(&priv->delta_msr_wait);
+       usb_reset_configuration(serial->dev);
+@@ -868,12 +866,16 @@ static int cypress_ioctl(struct tty_stru
+       switch (cmd) {
+       /* This code comes from drivers/char/serial.c and ftdi_sio.c */
+       case TIOCMIWAIT:
+-              while (priv != NULL) {
+-                      interruptible_sleep_on(&priv->delta_msr_wait);
++              for (;;) {
++                      interruptible_sleep_on(&port->delta_msr_wait);
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
+-                      else {
++
++                      if (port->serial->disconnected)
++                              return -EIO;
++
++                      {
+                               char diff = priv->diff_status;
+                               if (diff == 0)
+                                       return -EIO; /* no change => error */
+@@ -1187,7 +1189,7 @@ static void cypress_read_int_callback(st
+       if (priv->current_status != priv->prev_status) {
+               priv->diff_status |= priv->current_status ^
+                       priv->prev_status;
+-              wake_up_interruptible(&priv->delta_msr_wait);
++              wake_up_interruptible(&port->delta_msr_wait);
+               priv->prev_status = priv->current_status;
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/queue-3.8/usb-f81232-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-f81232-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..d6213d1
--- /dev/null
@@ -0,0 +1,65 @@
+From 508f940f1407656076a2e7d8f7fa059b567ecac2 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:14 +0100
+Subject: USB: f81232: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 508f940f1407656076a2e7d8f7fa059b567ecac2 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/f81232.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/serial/f81232.c
++++ b/drivers/usb/serial/f81232.c
+@@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
+ struct f81232_private {
+       spinlock_t lock;
+-      wait_queue_head_t delta_msr_wait;
+       u8 line_control;
+       u8 line_status;
+ };
+@@ -112,7 +111,7 @@ static void f81232_process_read_urb(stru
+       line_status = priv->line_status;
+       priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
+       spin_unlock_irqrestore(&priv->lock, flags);
+-      wake_up_interruptible(&priv->delta_msr_wait);
++      wake_up_interruptible(&port->delta_msr_wait);
+       if (!urb->actual_length)
+               return;
+@@ -261,11 +260,14 @@ static int wait_modem_info(struct usb_se
+       spin_unlock_irqrestore(&priv->lock, flags);
+       while (1) {
+-              interruptible_sleep_on(&priv->delta_msr_wait);
++              interruptible_sleep_on(&port->delta_msr_wait);
+               /* see if a signal did it */
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
++              if (port->serial->disconnected)
++                      return -EIO;
++
+               spin_lock_irqsave(&priv->lock, flags);
+               status = priv->line_status;
+               spin_unlock_irqrestore(&priv->lock, flags);
+@@ -327,7 +329,6 @@ static int f81232_port_probe(struct usb_
+               return -ENOMEM;
+       spin_lock_init(&priv->lock);
+-      init_waitqueue_head(&priv->delta_msr_wait);
+       usb_set_serial_port_data(port, priv);
diff --git a/queue-3.8/usb-ftdi_sio-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-ftdi_sio-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..3d916e0
--- /dev/null
@@ -0,0 +1,98 @@
+From 71ccb9b01981fabae27d3c98260ea4613207618e Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:15 +0100
+Subject: USB: ftdi_sio: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 71ccb9b01981fabae27d3c98260ea4613207618e upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+When switching to tty ports, some lifetime assumptions were changed.
+Specifically, close can now be called before the final tty reference is
+dropped as part of hangup at device disconnect. Even with the ftdi
+private-data refcounting this means that the port private data can be
+freed while a process is sleeping on modem-status changes and thus
+cannot be relied on to detect disconnects when woken up.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ftdi_sio.c |   19 ++++++++-----------
+ 1 file changed, 8 insertions(+), 11 deletions(-)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -69,9 +69,7 @@ struct ftdi_private {
+       int flags;              /* some ASYNC_xxxx flags are supported */
+       unsigned long last_dtr_rts;     /* saved modem control outputs */
+       struct async_icount     icount;
+-      wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+       char prev_status;        /* Used for TIOCMIWAIT */
+-      bool dev_gone;        /* Used to abort TIOCMIWAIT */
+       char transmit_empty;    /* If transmitter is empty or not */
+       __u16 interface;        /* FT2232C, FT2232H or FT4232H port interface
+                                  (0 for FT232/245) */
+@@ -1692,10 +1690,8 @@ static int ftdi_sio_port_probe(struct us
+       kref_init(&priv->kref);
+       mutex_init(&priv->cfg_lock);
+-      init_waitqueue_head(&priv->delta_msr_wait);
+       priv->flags = ASYNC_LOW_LATENCY;
+-      priv->dev_gone = false;
+       if (quirk && quirk->port_probe)
+               quirk->port_probe(priv);
+@@ -1841,8 +1837,7 @@ static int ftdi_sio_port_remove(struct u
+ {
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
+-      priv->dev_gone = true;
+-      wake_up_interruptible_all(&priv->delta_msr_wait);
++      wake_up_interruptible(&port->delta_msr_wait);
+       remove_sysfs_attrs(port);
+@@ -1991,7 +1986,7 @@ static int ftdi_process_packet(struct tt
+               if (diff_status & FTDI_RS0_RLSD)
+                       priv->icount.dcd++;
+-              wake_up_interruptible_all(&priv->delta_msr_wait);
++              wake_up_interruptible(&port->delta_msr_wait);
+               priv->prev_status = status;
+       }
+@@ -2448,11 +2443,15 @@ static int ftdi_ioctl(struct tty_struct
+        */
+       case TIOCMIWAIT:
+               cprev = priv->icount;
+-              while (!priv->dev_gone) {
+-                      interruptible_sleep_on(&priv->delta_msr_wait);
++              for (;;) {
++                      interruptible_sleep_on(&port->delta_msr_wait);
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
++
++                      if (port->serial->disconnected)
++                              return -EIO;
++
+                       cnow = priv->icount;
+                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+@@ -2462,8 +2461,6 @@ static int ftdi_ioctl(struct tty_struct
+                       }
+                       cprev = cnow;
+               }
+-              return -EIO;
+-              break;
+       case TIOCSERGETLSR:
+               return get_lsr_info(port, (struct serial_struct __user *)arg);
+               break;
diff --git a/queue-3.8/usb-io_edgeport-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-io_edgeport-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..9398d53
--- /dev/null
@@ -0,0 +1,69 @@
+From 333576255d4cfc53efd056aad438568184b36af6 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:16 +0100
+Subject: USB: io_edgeport: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 333576255d4cfc53efd056aad438568184b36af6 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/io_edgeport.c |   12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -110,7 +110,6 @@ struct edgeport_port {
+       wait_queue_head_t       wait_chase;             /* for handling sleeping while waiting for chase to finish */
+       wait_queue_head_t       wait_open;              /* for handling sleeping while waiting for open to finish */
+       wait_queue_head_t       wait_command;           /* for handling sleeping while waiting for command to finish */
+-      wait_queue_head_t       delta_msr_wait;         /* for handling sleeping while waiting for msr change to happen */
+       struct async_icount     icount;
+       struct usb_serial_port  *port;                  /* loop back to the owner of this object */
+@@ -884,7 +883,6 @@ static int edge_open(struct tty_struct *
+       /* initialize our wait queues */
+       init_waitqueue_head(&edge_port->wait_open);
+       init_waitqueue_head(&edge_port->wait_chase);
+-      init_waitqueue_head(&edge_port->delta_msr_wait);
+       init_waitqueue_head(&edge_port->wait_command);
+       /* initialize our icount structure */
+@@ -1669,13 +1667,17 @@ static int edge_ioctl(struct tty_struct
+               dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number);
+               cprev = edge_port->icount;
+               while (1) {
+-                      prepare_to_wait(&edge_port->delta_msr_wait,
++                      prepare_to_wait(&port->delta_msr_wait,
+                                               &wait, TASK_INTERRUPTIBLE);
+                       schedule();
+-                      finish_wait(&edge_port->delta_msr_wait, &wait);
++                      finish_wait(&port->delta_msr_wait, &wait);
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
++
++                      if (port->serial->disconnected)
++                              return -EIO;
++
+                       cnow = edge_port->icount;
+                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+@@ -2055,7 +2057,7 @@ static void handle_new_msr(struct edgepo
+                       icount->dcd++;
+               if (newMsr & EDGEPORT_MSR_DELTA_RI)
+                       icount->rng++;
+-              wake_up_interruptible(&edge_port->delta_msr_wait);
++              wake_up_interruptible(&edge_port->port->delta_msr_wait);
+       }
+       /* Save the new modem status */
diff --git a/queue-3.8/usb-io_ti-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-io_ti-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..2f49439
--- /dev/null
@@ -0,0 +1,67 @@
+From 7b2459690584f239650a365f3411ba2ec1c6d1e0 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:17 +0100
+Subject: USB: io_ti: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 7b2459690584f239650a365f3411ba2ec1c6d1e0 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/io_ti.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -87,9 +87,6 @@ struct edgeport_port {
+       int close_pending;
+       int lsr_event;
+       struct async_icount     icount;
+-      wait_queue_head_t       delta_msr_wait; /* for handling sleeping while
+-                                                 waiting for msr change to
+-                                                 happen */
+       struct edgeport_serial  *edge_serial;
+       struct usb_serial_port  *port;
+       __u8 bUartMode;         /* Port type, 0: RS232, etc. */
+@@ -1518,7 +1515,7 @@ static void handle_new_msr(struct edgepo
+                       icount->dcd++;
+               if (msr & EDGEPORT_MSR_DELTA_RI)
+                       icount->rng++;
+-              wake_up_interruptible(&edge_port->delta_msr_wait);
++              wake_up_interruptible(&edge_port->port->delta_msr_wait);
+       }
+       /* Save the new modem status */
+@@ -1821,7 +1818,6 @@ static int edge_open(struct tty_struct *
+       dev = port->serial->dev;
+       memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
+-      init_waitqueue_head(&edge_port->delta_msr_wait);
+       /* turn off loopback */
+       status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
+@@ -2488,10 +2484,14 @@ static int edge_ioctl(struct tty_struct
+               dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
+               cprev = edge_port->icount;
+               while (1) {
+-                      interruptible_sleep_on(&edge_port->delta_msr_wait);
++                      interruptible_sleep_on(&port->delta_msr_wait);
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
++
++                      if (port->serial->disconnected)
++                              return -EIO;
++
+                       cnow = edge_port->icount;
+                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
diff --git a/queue-3.8/usb-mct_u232-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-mct_u232-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..e6dc555
--- /dev/null
@@ -0,0 +1,70 @@
+From cf1d24443677a0758cfa88ca40f24858b89261c0 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:18 +0100
+Subject: USB: mct_u232: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit cf1d24443677a0758cfa88ca40f24858b89261c0 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/mct_u232.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/serial/mct_u232.c
++++ b/drivers/usb/serial/mct_u232.c
+@@ -114,8 +114,6 @@ struct mct_u232_private {
+       unsigned char        last_msr;      /* Modem Status Register */
+       unsigned int         rx_flags;      /* Throttling flags */
+       struct async_icount  icount;
+-      wait_queue_head_t    msr_wait;  /* for handling sleeping while waiting
+-                                              for msr change to happen */
+ };
+ #define THROTTLED             0x01
+@@ -409,7 +407,6 @@ static int mct_u232_port_probe(struct us
+               return -ENOMEM;
+       spin_lock_init(&priv->lock);
+-      init_waitqueue_head(&priv->msr_wait);
+       usb_set_serial_port_data(port, priv);
+@@ -606,7 +603,7 @@ static void mct_u232_read_int_callback(s
+               tty_kref_put(tty);
+       }
+ #endif
+-      wake_up_interruptible(&priv->msr_wait);
++      wake_up_interruptible(&port->delta_msr_wait);
+       spin_unlock_irqrestore(&priv->lock, flags);
+ exit:
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
+@@ -815,13 +812,17 @@ static int  mct_u232_ioctl(struct tty_st
+               cprev = mct_u232_port->icount;
+               spin_unlock_irqrestore(&mct_u232_port->lock, flags);
+               for ( ; ; ) {
+-                      prepare_to_wait(&mct_u232_port->msr_wait,
++                      prepare_to_wait(&port->delta_msr_wait,
+                                       &wait, TASK_INTERRUPTIBLE);
+                       schedule();
+-                      finish_wait(&mct_u232_port->msr_wait, &wait);
++                      finish_wait(&port->delta_msr_wait, &wait);
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
++
++                      if (port->serial->disconnected)
++                              return -EIO;
++
+                       spin_lock_irqsave(&mct_u232_port->lock, flags);
+                       cnow = mct_u232_port->icount;
+                       spin_unlock_irqrestore(&mct_u232_port->lock, flags);
diff --git a/queue-3.8/usb-mos7840-fix-broken-tiocmiwait.patch b/queue-3.8/usb-mos7840-fix-broken-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..de933e1
--- /dev/null
@@ -0,0 +1,42 @@
+From e670c6af12517d08a403487b1122eecf506021cf Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:19 +0100
+Subject: USB: mos7840: fix broken TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit e670c6af12517d08a403487b1122eecf506021cf upstream.
+
+Make sure waiting processes are woken on modem-status changes.
+
+Currently processes are only woken on termios changes regardless of
+whether the modem status has changed.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/mos7840.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -423,6 +423,9 @@ static void mos7840_handle_new_msr(struc
+                       icount->rng++;
+                       smp_wmb();
+               }
++
++              mos7840_port->delta_msr_cond = 1;
++              wake_up_interruptible(&mos7840_port->delta_msr_wait);
+       }
+ }
+@@ -2021,8 +2024,6 @@ static void mos7840_change_port_settings
+                       mos7840_port->read_urb_busy = false;
+               }
+       }
+-      wake_up(&mos7840_port->delta_msr_wait);
+-      mos7840_port->delta_msr_cond = 1;
+       dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__,
+               mos7840_port->shadowLCR);
+ }
diff --git a/queue-3.8/usb-mos7840-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-mos7840-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..363d17d
--- /dev/null
@@ -0,0 +1,70 @@
+From a14430db686b8e459e1cf070a6ecf391515c9ab9 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:20 +0100
+Subject: USB: mos7840: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit a14430db686b8e459e1cf070a6ecf391515c9ab9 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/mos7840.c |   13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -219,7 +219,6 @@ struct moschip_port {
+       char open;
+       char open_ports;
+       wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
+-      wait_queue_head_t delta_msr_wait;       /* for handling sleeping while waiting for msr change to happen */
+       int delta_msr_cond;
+       struct async_icount icount;
+       struct usb_serial_port *port;   /* loop back to the owner of this object */
+@@ -425,7 +424,7 @@ static void mos7840_handle_new_msr(struc
+               }
+               mos7840_port->delta_msr_cond = 1;
+-              wake_up_interruptible(&mos7840_port->delta_msr_wait);
++              wake_up_interruptible(&port->port->delta_msr_wait);
+       }
+ }
+@@ -1134,7 +1133,6 @@ static int mos7840_open(struct tty_struc
+       /* initialize our wait queues */
+       init_waitqueue_head(&mos7840_port->wait_chase);
+-      init_waitqueue_head(&mos7840_port->delta_msr_wait);
+       /* initialize our icount structure */
+       memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
+@@ -2224,13 +2222,18 @@ static int mos7840_ioctl(struct tty_stru
+               while (1) {
+                       /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
+                       mos7840_port->delta_msr_cond = 0;
+-                      wait_event_interruptible(mos7840_port->delta_msr_wait,
+-                                               (mos7840_port->
++                      wait_event_interruptible(port->delta_msr_wait,
++                                               (port->serial->disconnected ||
++                                                mos7840_port->
+                                                 delta_msr_cond == 1));
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
++
++                      if (port->serial->disconnected)
++                              return -EIO;
++
+                       cnow = mos7840_port->icount;
+                       smp_rmb();
+                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
diff --git a/queue-3.8/usb-oti6858-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-oti6858-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..4682754
--- /dev/null
@@ -0,0 +1,66 @@
+From 8edfdab37157d2683e51b8be5d3d5697f66a9f7b Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:21 +0100
+Subject: USB: oti6858: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 8edfdab37157d2683e51b8be5d3d5697f66a9f7b upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/oti6858.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -188,7 +188,6 @@ struct oti6858_private {
+       u8 setup_done;
+       struct delayed_work delayed_setup_work;
+-      wait_queue_head_t intr_wait;
+       struct usb_serial_port *port;   /* USB port with which associated */
+ };
+@@ -339,7 +338,6 @@ static int oti6858_port_probe(struct usb
+               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);
+@@ -664,11 +662,15 @@ static int wait_modem_info(struct usb_se
+       spin_unlock_irqrestore(&priv->lock, flags);
+       while (1) {
+-              wait_event_interruptible(priv->intr_wait,
++              wait_event_interruptible(port->delta_msr_wait,
++                                      port->serial->disconnected ||
+                                       priv->status.pin_state != prev);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
++              if (port->serial->disconnected)
++                      return -EIO;
++
+               spin_lock_irqsave(&priv->lock, flags);
+               status = priv->status.pin_state & PIN_MASK;
+               spin_unlock_irqrestore(&priv->lock, flags);
+@@ -763,7 +765,7 @@ static void oti6858_read_int_callback(st
+               if (!priv->transient) {
+                       if (xs->pin_state != priv->status.pin_state)
+-                              wake_up_interruptible(&priv->intr_wait);
++                              wake_up_interruptible(&port->delta_msr_wait);
+                       memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
+               }
diff --git a/queue-3.8/usb-pl2303-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-pl2303-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..5522eeb
--- /dev/null
@@ -0,0 +1,74 @@
+From 40509ca982c00c4b70fc00be887509feca0bff15 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:22 +0100
+Subject: USB: pl2303: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 40509ca982c00c4b70fc00be887509feca0bff15 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/pl2303.c |   11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -139,7 +139,6 @@ struct pl2303_serial_private {
+ struct pl2303_private {
+       spinlock_t lock;
+-      wait_queue_head_t delta_msr_wait;
+       u8 line_control;
+       u8 line_status;
+ };
+@@ -233,7 +232,6 @@ static int pl2303_port_probe(struct usb_
+               return -ENOMEM;
+       spin_lock_init(&priv->lock);
+-      init_waitqueue_head(&priv->delta_msr_wait);
+       usb_set_serial_port_data(port, priv);
+@@ -607,11 +605,14 @@ static int wait_modem_info(struct usb_se
+       spin_unlock_irqrestore(&priv->lock, flags);
+       while (1) {
+-              interruptible_sleep_on(&priv->delta_msr_wait);
++              interruptible_sleep_on(&port->delta_msr_wait);
+               /* see if a signal did it */
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
++              if (port->serial->disconnected)
++                      return -EIO;
++
+               spin_lock_irqsave(&priv->lock, flags);
+               status = priv->line_status;
+               spin_unlock_irqrestore(&priv->lock, flags);
+@@ -719,7 +720,7 @@ static void pl2303_update_line_status(st
+       spin_unlock_irqrestore(&priv->lock, flags);
+       if (priv->line_status & UART_BREAK_ERROR)
+               usb_serial_handle_break(port);
+-      wake_up_interruptible(&priv->delta_msr_wait);
++      wake_up_interruptible(&port->delta_msr_wait);
+       tty = tty_port_tty_get(&port->port);
+       if (!tty)
+@@ -784,7 +785,7 @@ static void pl2303_process_read_urb(stru
+       line_status = priv->line_status;
+       priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
+       spin_unlock_irqrestore(&priv->lock, flags);
+-      wake_up_interruptible(&priv->delta_msr_wait);
++      wake_up_interruptible(&port->delta_msr_wait);
+       if (!urb->actual_length)
+               return;
diff --git a/queue-3.8/usb-quatech2-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-quatech2-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..8ec558d
--- /dev/null
@@ -0,0 +1,71 @@
+From 69f87f40d2b98e8b4ab82a121fd2bd584690b887 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:23 +0100
+Subject: USB: quatech2: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 69f87f40d2b98e8b4ab82a121fd2bd584690b887 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/quatech2.c |   12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/quatech2.c
++++ b/drivers/usb/serial/quatech2.c
+@@ -128,7 +128,6 @@ struct qt2_port_private {
+       u8          shadowLSR;
+       u8          shadowMSR;
+-      wait_queue_head_t   delta_msr_wait; /* Used for TIOCMIWAIT */
+       struct async_icount icount;
+       struct usb_serial_port *port;
+@@ -506,8 +505,9 @@ static int wait_modem_info(struct usb_se
+       spin_unlock_irqrestore(&priv->lock, flags);
+       while (1) {
+-              wait_event_interruptible(priv->delta_msr_wait,
+-                                       ((priv->icount.rng != prev.rng) ||
++              wait_event_interruptible(port->delta_msr_wait,
++                                       (port->serial->disconnected ||
++                                        (priv->icount.rng != prev.rng) ||
+                                         (priv->icount.dsr != prev.dsr) ||
+                                         (priv->icount.dcd != prev.dcd) ||
+                                         (priv->icount.cts != prev.cts)));
+@@ -515,6 +515,9 @@ static int wait_modem_info(struct usb_se
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
++              if (port->serial->disconnected)
++                      return -EIO;
++
+               spin_lock_irqsave(&priv->lock, flags);
+               cur = priv->icount;
+               spin_unlock_irqrestore(&priv->lock, flags);
+@@ -841,7 +844,6 @@ static int qt2_port_probe(struct usb_ser
+       spin_lock_init(&port_priv->lock);
+       spin_lock_init(&port_priv->urb_lock);
+-      init_waitqueue_head(&port_priv->delta_msr_wait);
+       port_priv->port = port;
+       port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+@@ -984,7 +986,7 @@ static void qt2_update_msr(struct usb_se
+               if (newMSR & UART_MSR_TERI)
+                       port_priv->icount.rng++;
+-              wake_up_interruptible(&port_priv->delta_msr_wait);
++              wake_up_interruptible(&port->delta_msr_wait);
+       }
+ }
diff --git a/queue-3.8/usb-spcp8x5-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-spcp8x5-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..a85ee8e
--- /dev/null
@@ -0,0 +1,66 @@
+From dbcea7615d8d7d58f6ff49d2c5568113f70effe9 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:24 +0100
+Subject: USB: spcp8x5: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit dbcea7615d8d7d58f6ff49d2c5568113f70effe9 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/spcp8x5.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/serial/spcp8x5.c
++++ b/drivers/usb/serial/spcp8x5.c
+@@ -149,7 +149,6 @@ enum spcp8x5_type {
+ struct spcp8x5_private {
+       spinlock_t      lock;
+       enum spcp8x5_type       type;
+-      wait_queue_head_t       delta_msr_wait;
+       u8                      line_control;
+       u8                      line_status;
+ };
+@@ -179,7 +178,6 @@ static int spcp8x5_port_probe(struct usb
+               return -ENOMEM;
+       spin_lock_init(&priv->lock);
+-      init_waitqueue_head(&priv->delta_msr_wait);
+       priv->type = type;
+       usb_set_serial_port_data(port , priv);
+@@ -476,7 +474,7 @@ static void spcp8x5_process_read_urb(str
+       priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
+       spin_unlock_irqrestore(&priv->lock, flags);
+       /* wake up the wait for termios */
+-      wake_up_interruptible(&priv->delta_msr_wait);
++      wake_up_interruptible(&port->delta_msr_wait);
+       if (!urb->actual_length)
+               return;
+@@ -526,12 +524,15 @@ static int spcp8x5_wait_modem_info(struc
+       while (1) {
+               /* wake up in bulk read */
+-              interruptible_sleep_on(&priv->delta_msr_wait);
++              interruptible_sleep_on(&port->delta_msr_wait);
+               /* see if a signal did it */
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
++              if (port->serial->disconnected)
++                      return -EIO;
++
+               spin_lock_irqsave(&priv->lock, flags);
+               status = priv->line_status;
+               spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/queue-3.8/usb-ssu100-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-ssu100-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..d3ec81b
--- /dev/null
@@ -0,0 +1,71 @@
+From 43a66b4c417ad15f6d2f632ce67ad195bdf999e8 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:25 +0100
+Subject: USB: ssu100: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 43a66b4c417ad15f6d2f632ce67ad195bdf999e8 upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ssu100.c |   12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/ssu100.c
++++ b/drivers/usb/serial/ssu100.c
+@@ -61,7 +61,6 @@ struct ssu100_port_private {
+       spinlock_t status_lock;
+       u8 shadowLSR;
+       u8 shadowMSR;
+-      wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+       struct async_icount icount;
+ };
+@@ -355,8 +354,9 @@ static int wait_modem_info(struct usb_se
+       spin_unlock_irqrestore(&priv->status_lock, flags);
+       while (1) {
+-              wait_event_interruptible(priv->delta_msr_wait,
+-                                       ((priv->icount.rng != prev.rng) ||
++              wait_event_interruptible(port->delta_msr_wait,
++                                       (port->serial->disconnected ||
++                                        (priv->icount.rng != prev.rng) ||
+                                         (priv->icount.dsr != prev.dsr) ||
+                                         (priv->icount.dcd != prev.dcd) ||
+                                         (priv->icount.cts != prev.cts)));
+@@ -364,6 +364,9 @@ static int wait_modem_info(struct usb_se
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
++              if (port->serial->disconnected)
++                      return -EIO;
++
+               spin_lock_irqsave(&priv->status_lock, flags);
+               cur = priv->icount;
+               spin_unlock_irqrestore(&priv->status_lock, flags);
+@@ -445,7 +448,6 @@ static int ssu100_port_probe(struct usb_
+               return -ENOMEM;
+       spin_lock_init(&priv->status_lock);
+-      init_waitqueue_head(&priv->delta_msr_wait);
+       usb_set_serial_port_data(port, priv);
+@@ -537,7 +539,7 @@ static void ssu100_update_msr(struct usb
+                       priv->icount.dcd++;
+               if (msr & UART_MSR_TERI)
+                       priv->icount.rng++;
+-              wake_up_interruptible(&priv->delta_msr_wait);
++              wake_up_interruptible(&port->delta_msr_wait);
+       }
+ }
diff --git a/queue-3.8/usb-ti_usb_3410_5052-fix-use-after-free-in-tiocmiwait.patch b/queue-3.8/usb-ti_usb_3410_5052-fix-use-after-free-in-tiocmiwait.patch
new file mode 100644 (file)
index 0000000..a9ce3d3
--- /dev/null
@@ -0,0 +1,64 @@
+From fc98ab873aa3dbe783ce56a2ffdbbe7c7609521a Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Tue, 19 Mar 2013 09:21:26 +0100
+Subject: USB: ti_usb_3410_5052: fix use-after-free in TIOCMIWAIT
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit fc98ab873aa3dbe783ce56a2ffdbbe7c7609521a upstream.
+
+Use the port wait queue and make sure to check the serial disconnected
+flag before accessing private port data after waking up.
+
+This is is needed as the private port data (including the wait queue
+itself) can be gone when waking up after a disconnect.
+
+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 |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -74,7 +74,6 @@ struct ti_port {
+       int                     tp_flags;
+       int                     tp_closing_wait;/* in .01 secs */
+       struct async_icount     tp_icount;
+-      wait_queue_head_t       tp_msr_wait;    /* wait for msr change */
+       wait_queue_head_t       tp_write_wait;
+       struct ti_device        *tp_tdev;
+       struct usb_serial_port  *tp_port;
+@@ -432,7 +431,6 @@ static int ti_port_probe(struct usb_seri
+       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);
+@@ -784,9 +782,13 @@ static int ti_ioctl(struct tty_struct *t
+               dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
+               cprev = tport->tp_icount;
+               while (1) {
+-                      interruptible_sleep_on(&tport->tp_msr_wait);
++                      interruptible_sleep_on(&port->delta_msr_wait);
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
++
++                      if (port->serial->disconnected)
++                              return -EIO;
++
+                       cnow = tport->tp_icount;
+                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+@@ -1400,7 +1402,7 @@ static void ti_handle_new_msr(struct ti_
+                       icount->dcd++;
+               if (msr & TI_MSR_DELTA_RI)
+                       icount->rng++;
+-              wake_up_interruptible(&tport->tp_msr_wait);
++              wake_up_interruptible(&tport->tp_port->delta_msr_wait);
+               spin_unlock_irqrestore(&tport->tp_lock, flags);
+       }