[PATCH] usbserial: Fixes leak in serial_open() error path.
authorLuiz Fernando Capitulino <lcapitulino@mandriva.com.br>
Fri, 12 May 2006 01:34:24 +0000 (22:34 -0300)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 12 May 2006 18:58:09 +0000 (11:58 -0700)
If serial_open() fails at the port assignment or mutex_lock_interruptible()
is interrupted, the 'serial' object will never be freed.

We should call kref_put() when those errors happens.

Signed-off-by: Luiz Fernando N. Capitulino <lcapitulino@mandriva.com.br>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/serial/usb-serial.c

index d9dceb4f57b9ec97951b3d535b565be73702da56..9c36f0ece20ff6b43631e860621198f694400d5f 100644 (file)
@@ -189,11 +189,15 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
 
        portNumber = tty->index - serial->minor;
        port = serial->port[portNumber];
-       if (!port)
-               return -ENODEV;
+       if (!port) {
+               retval = -ENODEV;
+               goto bailout_kref_put;
+       }
 
-       if (mutex_lock_interruptible(&port->mutex))
-               return -ERESTARTSYS;
+       if (mutex_lock_interruptible(&port->mutex)) {
+               retval = -ERESTARTSYS;
+               goto bailout_kref_put;
+       }
         
        ++port->open_count;
 
@@ -209,7 +213,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
                 * safe because we are called with BKL held */
                if (!try_module_get(serial->type->driver.owner)) {
                        retval = -ENODEV;
-                       goto bailout_kref_put;
+                       goto bailout_mutex_unlock;
                }
 
                /* only call the device specific open if this 
@@ -224,9 +228,10 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
 
 bailout_module_put:
        module_put(serial->type->driver.owner);
-bailout_kref_put:
+bailout_mutex_unlock:
        port->open_count = 0;
        mutex_unlock(&port->mutex);
+bailout_kref_put:
        kref_put(&serial->kref, destroy_serial);
        return retval;
 }