usb: core: Fix potential memory leak adding dyn USBdevice IDs

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:

c63fe8f6 (usb: core: add sanity checks when using bInterfaceClass with new_id)
1b9fb31f (usb: core: check for valid id_table when using the RefId feature)
52a6966c (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>
This commit is contained in:
Christian Engelmayer 2014-01-28 22:22:27 +01:00 committed by Greg Kroah-Hartman
parent 76f24e3f39
commit 7f196caffb

View File

@ -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;
@ -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);
@ -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);