USB: serial: refuse to open recently removed USB Serial devices
James Woodcock [Wed, 11 Feb 2009 15:06:53 +0000 (15:06 +0000)]
A USB-serial converter device is plugged into a system, and a process
opens it's device node.  If the device is physically removed whilst the
process still has its device node open, then other processes can
sucessfully open the now non-existent device's node.  I would expect
that open() on a device that has been physically removed should return
ENODEV.

This is manifesting itself with getty on my system.  I do the following:
1.  set up inittab to spawn getty on ttyUSB0, eg:
    T1:23:respawn:/sbin/getty -L ttyUSB0 115200 vt100
2.  Plug in USB-serial converter cable
3.  Wait for a login prompt on a terminal program attached to the serial
    cable
4.  Login
5.  Pull the USB-serial converter cable from the box
6.  getty doesn't realise that ttyUSB0 no longer exists as /dev/ttyUSB0
    can still be opened.
7.  Re-insert the USB-serial converter cable
8.  You should no longer get a login prompt over the serial cable, as
    the the USB-serial cable now shows up as /dev/ttyUSB1, and getty is
    trying to talk to /dev/ttyUSB0.

The attached patch will cause open("/dev/ttyUSB0", O_RDONLY) to return
ENODEV after the USB-serial converter has been pulled.  The patch was
created against 2.6.28.1.  I can supply it against something else if
needs be.  It is fairly simple, so should be OK.

I am using a pl2303 device, although I don't think that makes any
difference.

From: James Woodcock <James.Woodcock@ACULAB.COM>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

drivers/usb/serial/usb-serial.c

index 9a26178..7317289 100644 (file)
@@ -204,6 +204,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
                goto bailout_kref_put;
        }
 
+       if (port->serial->disconnected) {
+               retval = -ENODEV;
+               goto bailout_kref_put;
+       }
+
        if (mutex_lock_interruptible(&port->mutex)) {
                retval = -ERESTARTSYS;
                goto bailout_kref_put;