From b689eff89e7bcd450f76309671cdb1186bd4a48c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 9 Apr 2014 16:43:35 -0700 Subject: [PATCH] 3.4-stable patches 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-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-serial-add-modem-status-change-wait-queue.patch usb-serial-fix-hang-when-opening-port.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 --- queue-3.4/series | 16 +++ ...116-fix-use-after-free-in-tiocmiwait.patch | 67 ++++++++++++ ...341-fix-use-after-free-in-tiocmiwait.patch | 76 +++++++++++++ ..._m8-fix-use-after-free-in-tiocmiwait.patch | 74 +++++++++++++ ...sio-fix-use-after-free-in-tiocmiwait.patch | 100 ++++++++++++++++++ ...ort-fix-use-after-free-in-tiocmiwait.patch | 71 +++++++++++++ ..._ti-fix-use-after-free-in-tiocmiwait.patch | 69 ++++++++++++ ...232-fix-use-after-free-in-tiocmiwait.patch | 73 +++++++++++++ .../usb-mos7840-fix-broken-tiocmiwait.patch | 45 ++++++++ ...840-fix-use-after-free-in-tiocmiwait.patch | 72 +++++++++++++ ...858-fix-use-after-free-in-tiocmiwait.patch | 69 ++++++++++++ ...303-fix-use-after-free-in-tiocmiwait.patch | 76 +++++++++++++ ...l-add-modem-status-change-wait-queue.patch | 45 ++++++++ ...sb-serial-fix-hang-when-opening-port.patch | 37 +++++++ ...8x5-fix-use-after-free-in-tiocmiwait.patch | 71 +++++++++++++ ...100-fix-use-after-free-in-tiocmiwait.patch | 74 +++++++++++++ ...052-fix-use-after-free-in-tiocmiwait.patch | 69 ++++++++++++ 17 files changed, 1104 insertions(+) create mode 100644 queue-3.4/usb-ark3116-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-ch341-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-cypress_m8-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-ftdi_sio-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-io_edgeport-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-io_ti-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-mct_u232-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-mos7840-fix-broken-tiocmiwait.patch create mode 100644 queue-3.4/usb-mos7840-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-oti6858-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-pl2303-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-serial-add-modem-status-change-wait-queue.patch create mode 100644 queue-3.4/usb-serial-fix-hang-when-opening-port.patch create mode 100644 queue-3.4/usb-spcp8x5-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-ssu100-fix-use-after-free-in-tiocmiwait.patch create mode 100644 queue-3.4/usb-ti_usb_3410_5052-fix-use-after-free-in-tiocmiwait.patch diff --git a/queue-3.4/series b/queue-3.4/series index f8e8245cbab..c2506dd5050 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -54,3 +54,19 @@ alsa-hda-add-conexant-cx20751-2-3-4-codec-support.patch revert-alsa-hda-shut-up-pins-at-power-saving-mode-with-conexnat-codecs.patch alsa-hda-always-turn-on-pins-for-hdmi-dp.patch alsa-hda-fix-internal-mic-for-lenovo-ideapad-u300s.patch +usb-serial-add-modem-status-change-wait-queue.patch +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-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-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 +usb-serial-fix-hang-when-opening-port.patch diff --git a/queue-3.4/usb-ark3116-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-ark3116-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..7a0f617ce2d --- /dev/null +++ b/queue-3.4/usb-ark3116-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,67 @@ +From 923ab36b14cb557482a079b0d67ef80f90bbc410 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:11 +0100 +Subject: USB: ark3116: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -68,7 +68,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 */ + +@@ -148,7 +147,6 @@ static int ark3116_attach(struct usb_ser + if (!priv) + return -ENOMEM; + +- init_waitqueue_head(&priv->delta_msr_wait); + mutex_init(&priv->hw_lock); + spin_lock_init(&priv->status_lock); + +@@ -460,10 +458,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) && +@@ -584,7 +586,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.4/usb-ch341-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-ch341-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..1e31cc8b1c7 --- /dev/null +++ b/queue-3.4/usb-ch341-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,76 @@ +From d14eeaffa77b092812af5868f9bfed2c6502d786 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:12 +0100 +Subject: USB: ch341: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -82,7 +82,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 */ +@@ -262,7 +261,6 @@ static int ch341_attach(struct usb_seria + 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; + +@@ -299,7 +297,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) +@@ -502,7 +500,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: +@@ -528,11 +526,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.4/usb-cypress_m8-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-cypress_m8-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..65c927b15c3 --- /dev/null +++ b/queue-3.4/usb-cypress_m8-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,74 @@ +From 2d5a267e36781e0d81e4546d2e4ffc9f63474fdf Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:13 +0100 +Subject: USB: cypress_m8: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -125,7 +125,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 */ +@@ -475,7 +474,6 @@ static int generic_startup(struct usb_se + kfree(priv); + return -ENOMEM; + } +- init_waitqueue_head(&priv->delta_msr_wait); + + /* Skip reset for FRWD device. It is a workaound: + device hangs if it receives SET_CONFIGURE in Configured +@@ -919,12 +917,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 */ +@@ -1250,7 +1252,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.4/usb-ftdi_sio-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-ftdi_sio-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..a2aa23abf67 --- /dev/null +++ b/queue-3.4/usb-ftdi_sio-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,100 @@ +From 31b9905f62ed5c361a37bb6f59cbf414873da65b Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:15 +0100 +Subject: USB: ftdi_sio: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -74,9 +74,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 */ + struct usb_serial_port *port; + __u16 interface; /* FT2232C, FT2232H or FT4232H port interface +@@ -1746,10 +1744,8 @@ static int ftdi_sio_port_probe(struct us + kref_init(&priv->kref); + mutex_init(&priv->cfg_lock); + memset(&priv->icount, 0x00, sizeof(priv->icount)); +- 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); +@@ -1908,8 +1904,7 @@ static int ftdi_sio_port_remove(struct u + + dbg("%s", __func__); + +- priv->dev_gone = true; +- wake_up_interruptible_all(&priv->delta_msr_wait); ++ wake_up_interruptible(&port->delta_msr_wait); + + remove_sysfs_attrs(port); + +@@ -2064,7 +2059,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; + } + +@@ -2467,11 +2462,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)) || +@@ -2481,8 +2480,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.4/usb-io_edgeport-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-io_edgeport-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..782051103ff --- /dev/null +++ b/queue-3.4/usb-io_edgeport-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,71 @@ +From 0c384c6e92e05ecb3466060fffe7fb5e759de724 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:16 +0100 +Subject: USB: io_edgeport: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -114,7 +114,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 */ +@@ -1701,13 +1699,17 @@ static int edge_ioctl(struct tty_struct + dbg("%s (%d) TIOCMIWAIT", __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) +@@ -2088,7 +2090,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.4/usb-io_ti-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-io_ti-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..a16f2f5c69e --- /dev/null +++ b/queue-3.4/usb-io_ti-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,69 @@ +From 24d369d8ad2aea254f5685f6565bf31175a1c617 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:17 +0100 +Subject: USB: io_ti: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -91,9 +91,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. */ +@@ -1549,7 +1546,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 */ +@@ -1867,7 +1864,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); +@@ -2553,10 +2549,14 @@ static int edge_ioctl(struct tty_struct + dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); + 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.4/usb-mct_u232-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-mct_u232-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..c0d1b7ebfc5 --- /dev/null +++ b/queue-3.4/usb-mct_u232-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,73 @@ +From 4f8adbff06abdb87614b8cfae32d207683400c26 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:18 +0100 +Subject: USB: mct_u232: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -126,8 +126,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 +@@ -407,7 +405,6 @@ static int mct_u232_startup(struct usb_s + if (!priv) + return -ENOMEM; + spin_lock_init(&priv->lock); +- init_waitqueue_head(&priv->msr_wait); + usb_set_serial_port_data(serial->port[0], priv); + + init_waitqueue_head(&serial->port[0]->write_wait); +@@ -631,7 +628,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); +@@ -852,13 +849,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.4/usb-mos7840-fix-broken-tiocmiwait.patch b/queue-3.4/usb-mos7840-fix-broken-tiocmiwait.patch new file mode 100644 index 00000000000..8bb5b8f8d76 --- /dev/null +++ b/queue-3.4/usb-mos7840-fix-broken-tiocmiwait.patch @@ -0,0 +1,45 @@ +From 928ab2854c082067496ca91c0495a60b17d7bf9e Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:19 +0100 +Subject: USB: mos7840: fix broken TIOCMIWAIT + +From: Johan Hovold + +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 +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -453,6 +453,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); + } + } + +@@ -2074,8 +2077,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; + dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x", + mos7840_port->shadowLCR); + } diff --git a/queue-3.4/usb-mos7840-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-mos7840-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..e6898f29bb4 --- /dev/null +++ b/queue-3.4/usb-mos7840-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,72 @@ +From 82159cdc841eaf66435eadf6e084f0f2c5791cbe Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:20 +0100 +Subject: USB: mos7840: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -240,7 +240,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 */ +@@ -455,7 +454,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); + } + } + +@@ -1116,7 +1115,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)); +@@ -2285,13 +2283,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.4/usb-oti6858-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-oti6858-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..309adbfbc6d --- /dev/null +++ b/queue-3.4/usb-oti6858-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,69 @@ +From 5db2cb168b894409ec5e2dcc5672578538bdedee Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:21 +0100 +Subject: USB: oti6858: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +[bwh: Backported to 3.2: adjust context, indentation] +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -198,7 +198,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 */ + }; + +@@ -356,7 +355,6 @@ static int oti6858_startup(struct usb_se + 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; +@@ -703,11 +701,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); +@@ -819,7 +821,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.4/usb-pl2303-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-pl2303-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..2d48be71a2b --- /dev/null +++ b/queue-3.4/usb-pl2303-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,76 @@ +From 664e1221e7828164acc8431968fb933ed998bbb2 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:22 +0100 +Subject: USB: pl2303: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -149,7 +149,6 @@ enum pl2303_type { + + struct pl2303_private { + spinlock_t lock; +- wait_queue_head_t delta_msr_wait; + u8 line_control; + u8 line_status; + enum pl2303_type type; +@@ -203,7 +202,6 @@ static int pl2303_startup(struct usb_ser + 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); + } +@@ -595,11 +593,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); +@@ -721,7 +722,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) +@@ -788,7 +789,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.4/usb-serial-add-modem-status-change-wait-queue.patch b/queue-3.4/usb-serial-add-modem-status-change-wait-queue.patch new file mode 100644 index 00000000000..7a761827072 --- /dev/null +++ b/queue-3.4/usb-serial-add-modem-status-change-wait-queue.patch @@ -0,0 +1,45 @@ +From da07f4596510e8141e105c9502a25b568caba860 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:10 +0100 +Subject: USB: serial: add modem-status-change wait queue + +From: Johan Hovold + +commit e5b33dc9d16053c2ae4c2c669cf008829530364b upstream. + +Add modem-status-change wait queue to struct usb_serial_port that +subdrivers can use to implement TIOCMIWAIT. + +Currently subdrivers use a private wait queue which may have been +released when waking up after device disconnected. + +Note that we're adding a new wait queue rather than reusing the tty-port +one as we do not want to get woken up at hangup (yet). + +Signed-off-by: Johan Hovold +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/usb/serial.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/linux/usb/serial.h ++++ b/include/linux/usb/serial.h +@@ -66,6 +66,7 @@ + * port. + * @flags: usb serial port flags + * @write_wait: a wait_queue_head_t used by the port. ++ * @delta_msr_wait: modem-status-change wait queue + * @work: work queue entry for the line discipline waking up. + * @throttled: nonzero if the read urb is inactive to throttle the device + * @throttle_req: nonzero if the tty wants to throttle us +@@ -112,6 +113,7 @@ struct usb_serial_port { + + unsigned long flags; + wait_queue_head_t write_wait; ++ wait_queue_head_t delta_msr_wait; + struct work_struct work; + char throttled; + char throttle_req; diff --git a/queue-3.4/usb-serial-fix-hang-when-opening-port.patch b/queue-3.4/usb-serial-fix-hang-when-opening-port.patch new file mode 100644 index 00000000000..b33d4b3fd91 --- /dev/null +++ b/queue-3.4/usb-serial-fix-hang-when-opening-port.patch @@ -0,0 +1,37 @@ +From a796ce4827fcbbb269f9e105f6b852b0dec85217 Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Tue, 26 Mar 2013 10:49:55 +0800 +Subject: USB: serial: fix hang when opening port + +From: Ming Lei + +commit eba0e3c3a0ba7b96f01cbe997680f6a4401a0bfc upstream. + +Johan's 'fix use-after-free in TIOCMIWAIT' patchset[1] introduces +one bug which can cause kernel hang when opening port. + +This patch initialized the 'port->delta_msr_wait' waitqueue head +to fix the bug which is introduced in 3.9-rc4. + +[1], http://marc.info/?l=linux-usb&m=136368139627876&w=2 + +Signed-off-by: Ming Lei +Acked-by: Johan Hovold +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/usb-serial.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -908,6 +908,7 @@ int usb_serial_probe(struct usb_interfac + port->port.ops = &serial_port_ops; + port->serial = serial; + spin_lock_init(&port->lock); ++ init_waitqueue_head(&port->delta_msr_wait); + /* Keep this for private driver use for the moment but + should probably go away */ + INIT_WORK(&port->work, usb_serial_port_work); diff --git a/queue-3.4/usb-spcp8x5-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-spcp8x5-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..1673125817d --- /dev/null +++ b/queue-3.4/usb-spcp8x5-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,71 @@ +From d1baabc8006fd238ad8da4d734dc815a8de02362 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:24 +0100 +Subject: USB: spcp8x5: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +commit d1baabc8006fd238ad8da4d734dc815a8de02362 upstream. + +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 +[bwh: Backported to 3.2: adjust context, indentation] +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -162,7 +162,6 @@ static struct usb_driver spcp8x5_driver + struct spcp8x5_private { + spinlock_t lock; + enum spcp8x5_type type; +- wait_queue_head_t delta_msr_wait; + u8 line_control; + u8 line_status; + }; +@@ -196,7 +195,6 @@ static int spcp8x5_startup(struct usb_se + 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); + } +@@ -499,7 +497,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; +@@ -549,12 +547,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.4/usb-ssu100-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-ssu100-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..1418a04f64a --- /dev/null +++ b/queue-3.4/usb-ssu100-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,74 @@ +From a8d6465295472939d209947962e7319b555dc55c Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:25 +0100 +Subject: USB: ssu100: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +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 +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -77,7 +77,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; + }; + +@@ -386,8 +385,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))); +@@ -395,6 +395,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); +@@ -477,7 +480,6 @@ static int ssu100_attach(struct usb_seri + } + + 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); +@@ -563,7 +565,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.4/usb-ti_usb_3410_5052-fix-use-after-free-in-tiocmiwait.patch b/queue-3.4/usb-ti_usb_3410_5052-fix-use-after-free-in-tiocmiwait.patch new file mode 100644 index 00000000000..7871e2f2a3a --- /dev/null +++ b/queue-3.4/usb-ti_usb_3410_5052-fix-use-after-free-in-tiocmiwait.patch @@ -0,0 +1,69 @@ +From 3668b9c17765cacf411effc4fc6e44099ac30800 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 19 Mar 2013 09:21:26 +0100 +Subject: USB: ti_usb_3410_5052: fix use-after-free in TIOCMIWAIT + +From: Johan Hovold + +commit 3668b9c17765cacf411effc4fc6e44099ac30800 upstream. + +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 +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -75,7 +75,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; +@@ -430,7 +429,6 @@ static int ti_startup(struct usb_serial + 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)) { +@@ -827,9 +825,13 @@ static int ti_ioctl(struct tty_struct *t + dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); + 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) +@@ -1458,7 +1460,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); + } + -- 2.47.3