Commit baadf2a5 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

most: usb: fix double free on late probe failure



The MOST subsystem has a non-standard registration function which frees
the interface on registration failures and on deregistration.

This unsurprisingly leads to bugs in the MOST drivers, and a couple of
recent changes turned a reference underflow and use-after-free in the
USB driver into several double free and a use-after-free on late probe
failures.

Fixes: 723de0f9 ("staging: most: remove device from interface structure")
Fixes: 4b127090 ("most: usb: Fix use-after-free in hdm_disconnect")
Fixes: a8cc9e5f ("most: usb: hdm_probe: Fix calling put_device() before device initialization")
Cc: stable@vger.kernel.org
Cc: Christian Gromm <christian.gromm@microchip.com>
Cc: Victoria Votokina <Victoria.Votokina@kaspersky.com>
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
Link: https://patch.msgid.link/20251029093029.28922-1-johan@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 96cf8500
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -1058,7 +1058,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)

	ret = most_register_interface(&mdev->iface);
	if (ret)
		goto err_free_busy_urbs;
		return ret;

	mutex_lock(&mdev->io_mutex);
	if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 ||
@@ -1068,8 +1068,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
		if (!mdev->dci) {
			mutex_unlock(&mdev->io_mutex);
			most_deregister_interface(&mdev->iface);
			ret = -ENOMEM;
			goto err_free_busy_urbs;
			return -ENOMEM;
		}

		mdev->dci->dev.init_name = "dci";
@@ -1078,18 +1077,15 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
		mdev->dci->dev.release = release_dci;
		if (device_register(&mdev->dci->dev)) {
			mutex_unlock(&mdev->io_mutex);
			put_device(&mdev->dci->dev);
			most_deregister_interface(&mdev->iface);
			ret = -ENOMEM;
			goto err_free_dci;
			return -ENOMEM;
		}
		mdev->dci->usb_device = mdev->usb_device;
	}
	mutex_unlock(&mdev->io_mutex);
	return 0;
err_free_dci:
	put_device(&mdev->dci->dev);
err_free_busy_urbs:
	kfree(mdev->busy_urbs);

err_free_ep_address:
	kfree(mdev->ep_address);
err_free_cap: