Re: [PATCH 05/17] USB: Lock registered interfaces during manual driver binding

From: Alan Stern

Date: Thu Nov 05 2026 - 12:36:21 EST


On Thu, Nov 05, 2026 at 01:42:18PM +0200, Leon Romanovsky wrote:
> From: Leon Romanovsky <leonro@xxxxxxxxxx>
>
> Interface claims hold the USB device lock, but device_bind_driver()
> requires the target interface lock. Without it, trust-policy writes can
> race admission.

This says nothing about usb_driver_release_refused_claim() and the code
related to it. It is an incomplete description of the patch.

Note that nothing prevents drivers from using an interface they claim
before that interface is registered. For your scheme to work properly,
you should make sure the claim is authorized when
usb_driver_claim_interface() is called, not when the interface is
registered.

Alan Stern

> +/*
> + * The driver core refused to bind an interface that a sibling claimed before
> + * it was registered, and dropped the claim. Let the claimant release the
> + * interface instead of operating it with a bound interface but no driver.
> + */
> +void usb_driver_release_refused_claim(struct usb_interface *iface,
> + struct device_driver *claimant)
> +{
> + struct device *dev = &iface->dev;
> +
> + device_lock(dev);
> + if (!dev->driver && iface->condition == USB_INTERFACE_BOUND) {
> + dev->driver = claimant;
> + usb_unbind_interface(dev);
> + dev_set_drvdata(dev, NULL);
> + dev->driver = NULL;
> + }
> + device_unlock(dev);
> +}
> +
> /* returns 0 if no match, 1 if match */
> int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
> {
> diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
> index a738d03c23eac..d35a7710c8ef4 100644
> --- a/drivers/usb/core/message.c
> +++ b/drivers/usb/core/message.c
> @@ -2264,6 +2264,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
> */
> for (i = 0; i < nintf; ++i) {
> struct usb_interface *intf = cp->interface[i];
> + struct device_driver *claimant;
>
> if (intf->dev.of_node &&
> !of_device_is_available(intf->dev.of_node)) {
> @@ -2277,7 +2278,14 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
> dev_name(&intf->dev), configuration,
> intf->cur_altsetting->desc.bInterfaceNumber);
> device_enable_async_suspend(&intf->dev);
> + claimant = intf->dev.driver;
> + if (claimant && !try_module_get(claimant->owner))
> + claimant = NULL;
> ret = device_add(&intf->dev);
> + if (!ret && claimant && !intf->dev.driver)
> + usb_driver_release_refused_claim(intf, claimant);
> + if (claimant)
> + module_put(claimant->owner);
> if (ret != 0) {
> dev_err(&dev->dev, "device_add(%s) --> %d\n",
> dev_name(&intf->dev), ret);
> diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
> index a9b37aeb515be..293340a48b6c5 100644
> --- a/drivers/usb/core/usb.h
> +++ b/drivers/usb/core/usb.h
> @@ -49,6 +49,8 @@ extern int usb_set_isoch_delay(struct usb_device *dev);
> extern int usb_get_bos_descriptor(struct usb_device *dev);
> extern void usb_release_bos_descriptor(struct usb_device *dev);
> extern int usb_set_configuration(struct usb_device *dev, int configuration);
> +void usb_driver_release_refused_claim(struct usb_interface *iface,
> + struct device_driver *claimant);
> extern int usb_choose_configuration(struct usb_device *udev);
> extern int usb_generic_driver_probe(struct usb_device *udev);
> extern void usb_generic_driver_disconnect(struct usb_device *udev);
>
> --
> 2.56.0