Re: [PATCH 2/2] usb: gadget: u_ether: Protect dev->gadget access with dev->lock
From: Aldo Ariel Panzardo
Date: Sat Oct 10 2026 - 10:28:56 EST
On Wed, Sep 23, 2026 at 03:58:36PM +0800, Kuen-Han Tsai wrote:
> Extend dev->lock to protect dev->gadget across gether_set_gadget(),
> gether_detach_gadget(), eth_get_drvinfo(), and rx_submit().
Confirmed against mainline. The race is real: eth_get_drvinfo() runs from
ethtool independently of unbind, so its NULL check and the
dev->gadget->name / dev_name(&dev->gadget->dev) dereferences could race
gether_detach_gadget() clearing dev->gadget. Holding dev->lock across the
check and both dereferences, while gether_set_gadget() and
gether_detach_gadget() now update dev->gadget under the same lock, closes
it.
The rest holds up too. In rx_submit() the cached g is both read and
dereferenced (g->quirk_ep_out_aligned_size) inside the dev->lock section,
and it is only reached when dev->port_usb != NULL; since gether_disconnect()
nulls dev->port_usb and drains all I/O before any gether_detach_gadget(), a
non-NULL port_usb there implies a live gadget, so g is valid. Clearing
dev->gadget before device_move() in gether_detach_gadget() is fine --
nothing between the two reads dev->gadget and device_move() does not touch
it. No lock inversion either: the sole rtnl section is unrelated and never
nested under dev->lock, and the guarded regions only do strscpy/pointer
work, so nothing sleeps under the lock.
One note, not blocking: the struct comment now says the lock is held while
accessing gadget, but gether_connect() and gether_register_netdev() still
read dev->gadget unlocked. Those run on the set_alt()/setup path, which the
composite core serializes against unbind (gether_detach_gadget() is only
reached from the *_unbind callbacks), so they are safe -- the comment just
reads a touch broader than what is actually enforced.
Reviewed-by: Aldo Ariel Panzardo <qwe.aldo@xxxxxxxxx>