[PATCH v2] usb: gadget: raw_gadget: fix double free in raw_release

From: cuiyudong

Date: Thu Mar 26 2026 - 05:18:48 EST


In raw_release(), when unregister == true, there are two kref_put() calls:
1. Inside the unregister block (extra)
2. At out_put label

The refcount increments are:
- 1 ref from dev_new() in raw_open()
- 1 ref from kref_get() in raw_ioctl_run()

Total: 2 references.

The original code performed 3 kref_put() operations, which causes the refcount
to drop below zero and leads to a double free in dev_free().

Remove the extra kref_put() inside the unregister block to balance the
reference counter correctly.

Since the extra kref_put() triggers an immediate use-after-free condition
on the dev structure, KASAN reports a double-free instead of a refcount warning.

BUG: KASAN: double-free in dev_free+0x424/0x740
Fixes: f2c2e717642c ("usb: gadget: add raw-gadget interface")
Reported-by: syzbot+25612fe5ab3dcafc3aab@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://lore.kernel.org/all/69c401ad.a70a0220.23629d.0000.GAE@xxxxxxxxxx/
Signed-off-by: cuiyudong <cuiyudong@xxxxxxxxxx>
---
Changes in v2:
- Removed Tested-by tag (syzbot did not test the patch)
- Expanded commit description to explain refcount imbalance and KASAN report
---
drivers/usb/gadget/legacy/raw_gadget.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
index 4febf8dac7ca..a1fd3fdf1323 100644
--- a/drivers/usb/gadget/legacy/raw_gadget.c
+++ b/drivers/usb/gadget/legacy/raw_gadget.c
@@ -465,12 +465,10 @@ static int raw_release(struct inode *inode, struct file *fd)
dev_err(dev->dev,
"usb_gadget_unregister_driver() failed with %d\n",
ret);
- /* Matches kref_get() in raw_ioctl_run(). */
- kref_put(&dev->count, dev_free);
}

out_put:
- /* Matches dev_new() in raw_open(). */
+ /* Matches dev_new() in raw_open() and kref_get() in raw_ioctl_run(). */
kref_put(&dev->count, dev_free);
return ret;
}
--
2.25.1