Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -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);