Commit a34c72b3 authored by Alexey Khoroshilov's avatar Alexey Khoroshilov Committed by Greg Kroah-Hartman

staging: gdm724x: fix leak at failure path in gdm_usb_probe()

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: default avatarAlexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5e128475
...@@ -830,24 +830,19 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -830,24 +830,19 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id
if (bInterfaceNumber > NETWORK_INTERFACE) { if (bInterfaceNumber > NETWORK_INTERFACE) {
pr_info("not a network device\n"); pr_info("not a network device\n");
return -1; return -ENODEV;
} }
phy_dev = kmalloc(sizeof(struct phy_dev), GFP_ATOMIC); phy_dev = kzalloc(sizeof(struct phy_dev), GFP_KERNEL);
if (!phy_dev) { if (!phy_dev)
ret = -ENOMEM; return -ENOMEM;
goto out;
}
udev = kmalloc(sizeof(struct lte_udev), GFP_ATOMIC); udev = kzalloc(sizeof(struct lte_udev), GFP_KERNEL);
if (!udev) { if (!udev) {
ret = -ENOMEM; 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->priv_dev = (void *)udev;
phy_dev->send_hci_func = gdm_usb_hci_send; phy_dev->send_hci_func = gdm_usb_hci_send;
phy_dev->send_sdu_func = gdm_usb_sdu_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 ...@@ -858,7 +853,7 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id
ret = init_usb(udev); ret = init_usb(udev);
if (ret < 0) { if (ret < 0) {
pr_err("init_usb func failed\n"); pr_err("init_usb func failed\n");
goto out; goto err_init_usb;
} }
udev->intf = intf; udev->intf = intf;
...@@ -875,22 +870,21 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -875,22 +870,21 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id
ret = request_mac_address(udev); ret = request_mac_address(udev);
if (ret < 0) { if (ret < 0) {
pr_err("request Mac address failed\n"); pr_err("request Mac address failed\n");
goto out; goto err_mac_address;
} }
start_rx_proc(phy_dev); start_rx_proc(phy_dev);
out: usb_get_dev(usbdev);
usb_set_intfdata(intf, phy_dev);
if (ret < 0) { return 0;
kfree(phy_dev);
if (udev) { err_mac_address:
release_usb(udev); release_usb(udev);
err_init_usb:
kfree(udev); kfree(udev);
} err_udev:
} kfree(phy_dev);
usb_get_dev(usbdev);
usb_set_intfdata(intf, phy_dev);
return ret; return ret;
} }
......
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