5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lovekesh Solanki <redacted>
commit dd0eed9e165b1a6292f49e622e3dd0b7d99b106d upstream.
gadget_dev_ioctl() reads dev->gadget before acquiring dev->lock, but
dev->state is checked after acquiring the lock. Therefore a concurrent
bind can change the device state between these operations, which can
leave ioctl with a stale NULL gadget pointer and causing a NULL pointer
dereference at gadget->ops->ioctl.
Read dev->gadget while holding dev->lock so that the gadget pointer
and device state are sampled consistently.
Cc: stable <stable@kernel.org>
Reported-by: Eulgyu Kim <redacted>
Link: https://lore.kernel.org/all/20260824113510.1141236-1-jjy600901@snu.ac.kr/ (local)
Reported-by: Jaeyoung Chung <redacted>
Link: https://lore.kernel.org/all/20260824113510.1141236-1-jjy600901@snu.ac.kr/ (local)
Signed-off-by: Lovekesh Solanki <redacted>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
Link: https://patch.msgid.link/20260825171343.459630-1-lovekeshsolanki00@gmail.com (local)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/legacy/inode.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -1250,10 +1250,11 @@ out:
static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
{
struct dev_data *dev = fd->private_data;
- struct usb_gadget *gadget = dev->gadget;
+ struct usb_gadget *gadget;
long ret = -ENOTTY;
spin_lock_irq(&dev->lock);
+ gadget = dev->gadget;
if (dev->state == STATE_DEV_OPENED ||
dev->state == STATE_DEV_UNBOUND) {
/* Not bound to a UDC */