Commit 4340e885 authored by Al Borchers's avatar Al Borchers Committed by Greg Kroah-Hartman

[PATCH] USB: patch for oops in io_edgeport.c

I tracked down a problem that caused an oops in io_edgeport.c.

The oops is reliably reproduced by using an EdgePort USB serial
port in dosemu and then exiting dosemu.  When dosemu closed
the port the oops would occur.  (Tested in RH 7.3 2.4.18-10.)

The problem was that a USB cmd callback would come in after the
close with the tty struct freed, and the edge_bulk_out_cmd_callback
function would do a wakeup on the tty->write_wait queue.  The
tty struct was gone (I checked that tty->magic was bad) and the
wakeup would oops.

As you did in other places in io_edgeport.c, I added a check that
edge_port->open was true before using the edge_port->port->tty
struct.

I added a similar check in edge_bulk_out_data_callback, though
I never actually saw the problem here.

I notice that in 2.4.20 a check has been added to be sure that
edge_port->port->tty is not null--however, this is not enough
because the tty pointer is not set to null when the port is
closed.  An alternate solution in 2.4.20 would be to set the
usb_serial_port->tty pointer to null in usbserial.c serial_close().
This seems like a good thing to do in general, since the tty
struct should not be used after a close which frees it.  If
you would like I investigate this a bit more--it could affect
other usb serial drivers and reveal some hidden bugs.
parent 6c7a3c95
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
* *
* Version history: * Version history:
* *
* 2003_04_03 al borchers
* - fixed a bug (that shows up with dosemu) where the tty struct is
* used in a callback after it has been freed
*
* 2.3 2002_03_08 greg kroah-hartman * 2.3 2002_03_08 greg kroah-hartman
* - fixed bug when multiple devices were attached at the same time. * - fixed bug when multiple devices were attached at the same time.
* *
...@@ -918,7 +922,7 @@ static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs) ...@@ -918,7 +922,7 @@ static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs)
tty = edge_port->port->tty; tty = edge_port->port->tty;
if (tty) { if (tty && edge_port->open) {
/* let the tty driver wakeup if it has a special write_wakeup function */ /* let the tty driver wakeup if it has a special write_wakeup function */
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
(tty->ldisc.write_wakeup)(tty); (tty->ldisc.write_wakeup)(tty);
...@@ -975,7 +979,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs) ...@@ -975,7 +979,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs)
tty = edge_port->port->tty; tty = edge_port->port->tty;
/* tell the tty driver that something has changed */ /* tell the tty driver that something has changed */
if (tty) if (tty && edge_port->open)
wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->write_wait);
/* we have completed the command */ /* we have completed the command */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment