| From dd0eed9e165b1a6292f49e622e3dd0b7d99b106d Mon Sep 17 00:00:00 2001 |
| From: Lovekesh Solanki <lovekeshsolanki00@gmail.com> |
| Date: Tue, 25 Aug 2026 22:43:43 +0530 |
| Subject: USB: gadget: fix NULL pointer dereference in gadget_dev_ioctl() |
| |
| From: Lovekesh Solanki <lovekeshsolanki00@gmail.com> |
| |
| 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 <eulgyukim@snu.ac.kr> |
| Link: https://lore.kernel.org/all/20260824113510.1141236-1-jjy600901@snu.ac.kr/ |
| Reported-by: Jaeyoung Chung <jjy600901@snu.ac.kr> |
| Link: https://lore.kernel.org/all/20260824113510.1141236-1-jjy600901@snu.ac.kr/ |
| Signed-off-by: Lovekesh Solanki <lovekeshsolanki00@gmail.com> |
| Reviewed-by: Alan Stern <stern@rowland.harvard.edu> |
| Link: https://patch.msgid.link/20260825171343.459630-1-lovekeshsolanki00@gmail.com |
| 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 |
| @@ -1247,10 +1247,11 @@ out: |
| static long gadget_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 */ |