staging: gdm724x: fix leak at failure path in gdm_usb_probe()
authorAlexey Khoroshilov <khoroshilov@ispras.ru>
Fri, 15 Nov 2013 20:46:24 +0000 (00:46 +0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 25 Nov 2013 20:29:15 +0000 (12:29 -0800)
Error handling code in gdm_usb_probe() deallocates all resources,
but calls usb_get_dev(usbdev) and returns error code after that.

The patch fixes it and, by the way, several other issues:
- no need to use GFP_ATOMIC in probe();
- return -ENODEV instead of -1;
- kmalloc+memset -> kzalloc

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

Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/gdm724x/gdm_usb.c

index 781134a..33458a5 100644 (file)
@@ -830,24 +830,19 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id
 
        if (bInterfaceNumber > NETWORK_INTERFACE) {
                pr_info("not a network device\n");
-               return -1;
+               return -ENODEV;
        }
 
-       phy_dev = kmalloc(sizeof(struct phy_dev), GFP_ATOMIC);
-       if (!phy_dev) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       phy_dev = kzalloc(sizeof(struct phy_dev), GFP_KERNEL);
+       if (!phy_dev)
+               return -ENOMEM;
 
-       udev = kmalloc(sizeof(struct lte_udev), GFP_ATOMIC);
+       udev = kzalloc(sizeof(struct lte_udev), GFP_KERNEL);
        if (!udev) {
                ret = -ENOMEM;
-               goto out;
+               goto err_udev;
        }
 
-       memset(phy_dev, 0, sizeof(struct phy_dev));
-       memset(udev, 0, sizeof(struct lte_udev));
-
        phy_dev->priv_dev = (void *)udev;
        phy_dev->send_hci_func = gdm_usb_hci_send;
        phy_dev->send_sdu_func = gdm_usb_sdu_send;
@@ -858,7 +853,7 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id
        ret = init_usb(udev);
        if (ret < 0) {
                pr_err("init_usb func failed\n");
-               goto out;
+               goto err_init_usb;
        }
        udev->intf = intf;
 
@@ -875,23 +870,22 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id
        ret = request_mac_address(udev);
        if (ret < 0) {
                pr_err("request Mac address failed\n");
-               goto out;
+               goto err_mac_address;
        }
 
        start_rx_proc(phy_dev);
-out:
-
-       if (ret < 0) {
-               kfree(phy_dev);
-               if (udev) {
-                       release_usb(udev);
-                       kfree(udev);
-               }
-       }
-
        usb_get_dev(usbdev);
        usb_set_intfdata(intf, phy_dev);
 
+       return 0;
+
+err_mac_address:
+       release_usb(udev);
+err_init_usb:
+       kfree(udev);
+err_udev:
+       kfree(phy_dev);
+
        return ret;
 }