Skip to content

Commit

Permalink
usb: core: Fix potential memory leak adding dyn USBdevice IDs
Browse files Browse the repository at this point in the history
Fix a memory leak in the usb_store_new_id() error paths. When bailing out
due to sanity checks, the function left the already allocated usb_dynid
struct in place. This regression was introduced by the following commits:

c63fe8f (usb: core: add sanity checks when using bInterfaceClass with new_id)
1b9fb31 (usb: core: check for valid id_table when using the RefId feature)
52a6966 (usb: core: bail out if user gives an unknown RefId when using new_id)

Detected by Coverity: CID 1162604.

Signed-off-by: Christian Engelmayer <cengelma@gmx.at>
Acked-by: Wolfram Sang <wsa@the-dreams.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Christian Engelmayer authored and Greg Kroah-Hartman committed Feb 5, 2014
1 parent 76f24e3 commit 7f196ca
Showing 1 changed file with 17 additions and 7 deletions.
24 changes: 17 additions & 7 deletions drivers/usb/core/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
dynid->id.idProduct = idProduct;
dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
if (fields > 2 && bInterfaceClass) {
if (bInterfaceClass > 255)
return -EINVAL;
if (bInterfaceClass > 255) {
retval = -EINVAL;
goto fail;
}

dynid->id.bInterfaceClass = (u8)bInterfaceClass;
dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
Expand All @@ -73,17 +75,21 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
if (fields > 4) {
const struct usb_device_id *id = id_table;

if (!id)
return -ENODEV;
if (!id) {
retval = -ENODEV;
goto fail;
}

for (; id->match_flags; id++)
if (id->idVendor == refVendor && id->idProduct == refProduct)
break;

if (id->match_flags)
if (id->match_flags) {
dynid->id.driver_info = id->driver_info;
else
return -ENODEV;
} else {
retval = -ENODEV;
goto fail;
}
}

spin_lock(&dynids->lock);
Expand All @@ -95,6 +101,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
if (retval)
return retval;
return count;

fail:
kfree(dynid);
return retval;
}
EXPORT_SYMBOL_GPL(usb_store_new_id);

Expand Down

0 comments on commit 7f196ca

Please sign in to comment.