In the Linux kernel, the following vulnerability has been resolved:
USB: gadget: Fix obscure lockdep violation for udc_mutex
A recent commit expanding the scope of the udc_lock mutex in the gadget core managed to cause an obscure and slightly bizarre lockdep violation. In abbreviated form:
====================================================== WARNING: possible circular locking dependency detected
udevadm/312 is trying to acquire lock: ffff80000aae1058 (udclock){+.+.}-{3:3}, at: usbudc_uevent+0x54/0xe0
but task is already holding lock: ffff000002277548 (kn->active#4){++++}-{0:0}, at: kernfsseqstart+0x34/0xe0
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #3 (kn->active#4){++++}-{0:0}: lockacquire+0x68/0x84 _kernfsremove+0x268/0x380 kernfsremovebynamens+0x58/0xac sysfsremovefilens+0x18/0x24 device_del+0x15c/0x440
-> #2 (devicelinkslock){+.+.}-{3:3}: lockacquire+0x68/0x84 _mutexlock+0x9c/0x430 mutexlocknested+0x38/0x64 devicelinkremove+0x3c/0xa0 _regulatorput.part.0+0x168/0x190 regulatorput+0x3c/0x54 devmregulator_release+0x14/0x20
-> #1 (regulatorlistmutex){+.+.}-{3:3}: lockacquire+0x68/0x84 _mutexlock+0x9c/0x430 mutexlocknested+0x38/0x64 regulatorlockdependent+0x54/0x284 regulatorenable+0x34/0x80 phypoweron+0x24/0x130 _dwc2lowlevelhwenable+0x100/0x130 dwc2lowlevelhwenable+0x18/0x40 dwc2hsotgudcstart+0x6c/0x2f0 gadgetbinddriver+0x124/0x1f4
-> #0 (udclock){+.+.}-{3:3}: _lockacquire+0x1298/0x20cc lockacquire.part.0+0xe0/0x230 lockacquire+0x68/0x84 _mutexlock+0x9c/0x430 mutexlocknested+0x38/0x64 usbudc_uevent+0x54/0xe0
Evidently this was caused by the scope of udcmutex being too large. The mutex is only meant to protect udc->driver along with a few other things. As far as I can tell, there's no reason for the mutex to be held while the gadget core calls a gadget driver's ->bind or ->unbind routine, or while a UDC is being started or stopped. (This accounts for link #1 in the chain above, where the mutex is held while the dwc2hsotg_udc is started as part of driver probing.)
Gadget drivers' ->disconnect callbacks are problematic. Even though usbgadgetdisconnect() will now acquire the udcmutex, there's a window in usbgadgetbinddriver() between the times when the mutex is released and the ->bind callback is invoked. If a disconnect occurred during that window, we could call the driver's ->disconnect routine before its ->bind routine. To prevent this from happening, it will be necessary to prevent a UDC from connecting while it has no gadget driver. This should be done already but it doesn't seem to be; currently usbgadgetconnect() has no check for this. Such a check will have to be added later.
Some degree of mutual exclusion is required in softconnectstore(), which can dereference udc->driver at arbitrary times since it is a sysfs callback. The solution here is to acquire the gadget's device lock rather than the udcmutex. Since the driver core guarantees that the device lock is always held during driver binding and unbinding, this will make the accesses in softconnect_store() mutually exclusive with any changes to udc->driver.
Lastly, it turns out there is one place which should hold the udcmutex but currently does not: The functionshow() routine needs protection while it dereferences udc->driver. The missing lock and unlock calls are added.