Commit 7f196caf authored by Christian Engelmayer's avatar Christian Engelmayer Committed by Greg Kroah-Hartman

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: default avatarChristian Engelmayer <cengelma@gmx.at>
Acked-by: default avatarWolfram Sang <wsa@the-dreams.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 76f24e3f
...@@ -63,8 +63,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, ...@@ -63,8 +63,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
dynid->id.idProduct = idProduct; dynid->id.idProduct = idProduct;
dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE; dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
if (fields > 2 && bInterfaceClass) { if (fields > 2 && bInterfaceClass) {
if (bInterfaceClass > 255) if (bInterfaceClass > 255) {
return -EINVAL; retval = -EINVAL;
goto fail;
}
dynid->id.bInterfaceClass = (u8)bInterfaceClass; dynid->id.bInterfaceClass = (u8)bInterfaceClass;
dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS; dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
...@@ -73,17 +75,21 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, ...@@ -73,17 +75,21 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
if (fields > 4) { if (fields > 4) {
const struct usb_device_id *id = id_table; const struct usb_device_id *id = id_table;
if (!id) if (!id) {
return -ENODEV; retval = -ENODEV;
goto fail;
}
for (; id->match_flags; id++) for (; id->match_flags; id++)
if (id->idVendor == refVendor && id->idProduct == refProduct) if (id->idVendor == refVendor && id->idProduct == refProduct)
break; break;
if (id->match_flags) if (id->match_flags) {
dynid->id.driver_info = id->driver_info; dynid->id.driver_info = id->driver_info;
else } else {
return -ENODEV; retval = -ENODEV;
goto fail;
}
} }
spin_lock(&dynids->lock); spin_lock(&dynids->lock);
...@@ -95,6 +101,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, ...@@ -95,6 +101,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
if (retval) if (retval)
return retval; return retval;
return count; return count;
fail:
kfree(dynid);
return retval;
} }
EXPORT_SYMBOL_GPL(usb_store_new_id); EXPORT_SYMBOL_GPL(usb_store_new_id);
......
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