staging: lirc_sasem: fix NULL pointer dereference in sasem_probe
authorAlexey Khoroshilov <khoroshilov@ispras.ru>
Mon, 29 Aug 2011 20:54:21 +0000 (00:54 +0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 6 Sep 2011 18:46:21 +0000 (11:46 -0700)
If any memory allocation failed, goto alloc_status_switch
leads to mutex_unlock(&context->ctx_lock) while context is NULL.
The patch moves alloc_status_switch to handle error conditions
in correct way.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/lirc/lirc_sasem.c

index 7080cde..a2d18b0 100644 (file)
@@ -814,29 +814,6 @@ static int sasem_probe(struct usb_interface *interface,
                printk(KERN_INFO "%s: Registered Sasem driver (minor:%d)\n",
                        __func__, lirc_minor);
 
-alloc_status_switch:
-
-       switch (alloc_status) {
-
-       case 7:
-               if (vfd_ep_found)
-                       usb_free_urb(tx_urb);
-       case 6:
-               usb_free_urb(rx_urb);
-       case 5:
-               lirc_buffer_free(rbuf);
-       case 4:
-               kfree(rbuf);
-       case 3:
-               kfree(driver);
-       case 2:
-               kfree(context);
-               context = NULL;
-       case 1:
-               retval = -ENOMEM;
-               goto unlock;
-       }
-
        /* Needed while unregistering! */
        driver->minor = lirc_minor;
 
@@ -867,6 +844,29 @@ alloc_status_switch:
                        __func__, dev->bus->busnum, dev->devnum);
 unlock:
        mutex_unlock(&context->ctx_lock);
+
+alloc_status_switch:
+       switch (alloc_status) {
+
+       case 7:
+               if (vfd_ep_found)
+                       usb_free_urb(tx_urb);
+       case 6:
+               usb_free_urb(rx_urb);
+       case 5:
+               lirc_buffer_free(rbuf);
+       case 4:
+               kfree(rbuf);
+       case 3:
+               kfree(driver);
+       case 2:
+               kfree(context);
+               context = NULL;
+       case 1:
+               if (retval == 0)
+                       retval = -ENOMEM;
+       }
+
 exit:
        return retval;
 }