The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
@ 2026-07-31  1:28 syzbot
  2026-07-31  4:26 ` Forwarded: [PATCH] usb: gadgetfs: fix use-after-free in ep_open() syzbot
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: syzbot @ 2026-07-31  1:28 UTC (permalink / raw)
  To: gregkh, linux-kernel, linux-usb, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    365f9c7a6b81 Merge branches 'for-next/core' and 'for-next/..
git tree:       git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
console output: https://syzkaller.appspot.com/x/log.txt?x=13731632580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=72c97575381cec47
dashboard link: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
compiler:       Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
userspace arch: arm64
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=136d6499580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=138d6449580000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/eafe0adb7386/disk-365f9c7a.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/29422d607579/vmlinux-365f9c7a.xz
kernel image: https://storage.googleapis.com/syzbot-assets/98ca955a8b54/Image-365f9c7a.gz.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com

==================================================================
BUG: KASAN: slab-use-after-free in __mutex_lock_common kernel/locking/mutex.c:625 [inline]
BUG: KASAN: slab-use-after-free in __mutex_lock+0x130/0xf14 kernel/locking/mutex.c:821
Read of size 8 at addr ffff0000efe3d058 by task syz-executor/5909

CPU: 1 UID: 0 PID: 5909 Comm: syz-executor Not tainted syzkaller #0 PREEMPT 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/02/2026
Call trace:
 show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:499 (C)
 __dump_stack+0x30/0x40 lib/dump_stack.c:94
 dump_stack_lvl+0xd8/0x12c lib/dump_stack.c:120
 print_address_description+0xb0/0x238 mm/kasan/report.c:378
 print_report+0x68/0x84 mm/kasan/report.c:482
 kasan_report+0x8c/0xc4 mm/kasan/report.c:595
 __asan_report_load8_noabort+0x20/0x2c mm/kasan/report_generic.c:381
 __mutex_lock_common kernel/locking/mutex.c:625 [inline]
 __mutex_lock+0x130/0xf14 kernel/locking/mutex.c:821
 mutex_lock_interruptible_nested+0x24/0x30 kernel/locking/mutex.c:899
 ep_open+0x58/0x25c drivers/usb/gadget/legacy/inode.c:823
 do_dentry_open+0x5c4/0xfc0 fs/open.c:947
 vfs_open+0x44/0x2dc fs/open.c:1052
 do_open fs/namei.c:4700 [inline]
 path_openat+0x21fc/0x2a60 fs/namei.c:4863
 do_file_open+0x1c8/0x2e8 fs/namei.c:4892
 do_sys_openat2+0x114/0x1e8 fs/open.c:1368
 do_sys_open+0xb0/0xe0 fs/open.c:1374
 __do_sys_openat fs/open.c:1390 [inline]
 __se_sys_openat fs/open.c:1385 [inline]
 __arm64_sys_openat+0xa0/0xbc fs/open.c:1385
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x64/0x260 arch/arm64/kernel/entry-common.c:736
 el0t_64_sync_handler+0x48/0x148 arch/arm64/kernel/entry-common.c:755
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:594

Allocated by task 6282:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x40/0x78 mm/kasan/common.c:78
 kasan_save_alloc_info+0x44/0x54 mm/kasan/generic.c:570
 poison_kmalloc_redzone mm/kasan/common.c:398 [inline]
 __kasan_kmalloc+0x9c/0xb4 mm/kasan/common.c:415
 kasan_kmalloc include/linux/kasan.h:263 [inline]
 __kmalloc_cache_noprof+0x2e8/0x5ec mm/slub.c:5515
 _kmalloc_noprof include/linux/slab.h:969 [inline]
 _kzalloc_noprof include/linux/slab.h:1290 [inline]
 activate_ep_files drivers/usb/gadget/legacy/inode.c:1601 [inline]
 gadgetfs_bind+0x204/0x75c drivers/usb/gadget/legacy/inode.c:1692
 gadget_bind_driver+0x274/0x834 drivers/usb/gadget/udc/core.c:1662
 call_driver_probe drivers/base/dd.c:-1 [inline]
 really_probe+0x29c/0x800 drivers/base/dd.c:706
 __driver_probe_device+0x1e0/0x350 drivers/base/dd.c:868
 driver_probe_device+0x6c/0x19c drivers/base/dd.c:898
 __driver_attach+0x168/0x384 drivers/base/dd.c:1292
 bus_for_each_dev+0x128/0x1b4 drivers/base/bus.c:383
 driver_attach+0x50/0x60 drivers/base/dd.c:1310
 bus_add_driver+0x208/0x500 drivers/base/bus.c:763
 driver_register+0x220/0x310 drivers/base/driver.c:174
 usb_gadget_register_driver_owner+0xf0/0x25c drivers/usb/gadget/udc/core.c:1752
 dev_config+0x91c/0xcc0 drivers/usb/gadget/legacy/inode.c:1883
 vfs_write+0x2a4/0xa0c fs/read_write.c:685
 ksys_write+0x12c/0x228 fs/read_write.c:739
 __do_sys_write fs/read_write.c:750 [inline]
 __se_sys_write fs/read_write.c:747 [inline]
 __arm64_sys_write+0x7c/0x90 fs/read_write.c:747
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x64/0x260 arch/arm64/kernel/entry-common.c:736
 el0t_64_sync_handler+0x48/0x148 arch/arm64/kernel/entry-common.c:755
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:594

Freed by task 6283:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x40/0x78 mm/kasan/common.c:78
 kasan_save_free_info+0x58/0x70 mm/kasan/generic.c:584
 poison_slab_object mm/kasan/common.c:253 [inline]
 __kasan_slab_free+0x74/0xa4 mm/kasan/common.c:285
 kasan_slab_free include/linux/kasan.h:235 [inline]
 slab_free_hook mm/slub.c:2705 [inline]
 slab_free mm/slub.c:6405 [inline]
 kfree+0x188/0x690 mm/slub.c:6720
 put_ep+0xd0/0x144 drivers/usb/gadget/legacy/inode.c:225
 destroy_ep_files+0x244/0x2dc drivers/usb/gadget/legacy/inode.c:1582
 gadgetfs_unbind+0x114/0x1f0 drivers/usb/gadget/legacy/inode.c:1655
 gadget_unbind_driver+0x188/0x790 drivers/usb/gadget/udc/core.c:1724
 device_remove+0xc4/0x134 drivers/base/dd.c:616
 __device_release_driver drivers/base/dd.c:1349 [inline]
 device_release_driver_internal+0x124/0x20c drivers/base/dd.c:1372
 driver_detach+0x124/0x1b4 drivers/base/dd.c:1435
 bus_remove_driver+0x124/0x22c drivers/base/bus.c:832
 driver_unregister+0x78/0xac drivers/base/driver.c:202
 usb_gadget_unregister_driver+0x50/0x78 drivers/usb/gadget/udc/core.c:1784
 dev_release+0x8c/0x15c drivers/usb/gadget/legacy/inode.c:1198
 __fput+0x338/0x74c fs/file_table.c:512
 ____fput+0x20/0x30 fs/file_table.c:540
 task_work_run+0x1cc/0x25c kernel/task_work.c:233
 exit_task_work include/linux/task_work.h:40 [inline]
 do_exit+0x58c/0x1a74 kernel/exit.c:1009
 __do_sys_exit kernel/exit.c:1119 [inline]
 __se_sys_exit kernel/exit.c:1117 [inline]
 do_group_exit+0x0/0x238 kernel/exit.c:1117
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x64/0x260 arch/arm64/kernel/entry-common.c:736
 el0t_64_sync_handler+0x48/0x148 arch/arm64/kernel/entry-common.c:755
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:594

The buggy address belongs to the object at ffff0000efe3d000
 which belongs to the cache kmalloc-512 of size 512
The buggy address is located 88 bytes inside of
 freed 512-byte region [ffff0000efe3d000, ffff0000efe3d200)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff0000efe3dc00 pfn:0x12fe3c


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Forwarded: [PATCH] usb: gadgetfs: fix use-after-free in ep_open()
  2026-07-31  1:28 [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
@ 2026-07-31  4:26 ` syzbot
  2026-07-31  4:44 ` syzbot
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: syzbot @ 2026-07-31  4:26 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: [PATCH] usb: gadgetfs: fix use-after-free in ep_open()
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci


ep_open() dereferenced inode->i_private (an ep_data pointer) and
locked its embedded mutex before ever validating that the object was
still alive:

    struct ep_data *data = inode->i_private;
    if (mutex_lock_interruptible(&data->lock) != 0)
            return -EINTR;
    spin_lock_irq(&data->dev->lock);
    if (data->dev->state == STATE_DEV_UNBOUND)
            ...

The liveness check (dev->state == STATE_DEV_UNBOUND) only happened
*after* data->lock had already been touched. destroy_ep_files(),
called from gadgetfs_unbind(), can free the same ep_data
concurrently via put_ep(), since nothing prevented an in-flight
open() from racing the teardown. KASAN reports a slab-use-after-free
read inside __mutex_lock_common() from ep_open(), with the object
freed by a concurrent gadgetfs_unbind() -> destroy_ep_files() ->
put_ep() -> kfree() on another task.

This exact race was identified by Al Viro on LKML in 2006 ("races in
drivers/usb/gadget/inode.c"), including the correct fix direction,
but it was never applied to ep_open() itself. Later fixes to this
file (the udc_usage counter, CVE-2022-4382) hardened the I/O paths
and the mount/unmount race, but left this specific ordering bug in
place.

Fix it by reordering ep_open() so that dev->state and inode->i_private
are only read while holding dev->lock -- reached via
inode->i_sb->s_fs_info, which stays valid for the life of the mount,
independent of any individual ep_data -- and by pinning the object
with get_ep() before dev->lock is dropped and before data->lock is
touched. This guarantees put_ep()/kfree() cannot race the mutex lock
in ep_open().

This fix depends on dev->state being set to STATE_DEV_UNBOUND under
dev->lock before any call to destroy_ep_files(), so that ep_open()
seeing a "bound" state is a guarantee that no free is in progress.
gadgetfs_unbind() already does this correctly. activate_ep_files()'s
enomem0 error-cleanup path did not: it called destroy_ep_files()
directly without first setting dev->state, which would have left the
same race open on the bind-failure path. This patch adds the missing
state transition there as well, so the invariant holds for every
caller of destroy_ep_files().

Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 drivers/usb/gadget/legacy/inode.c | 37 ++++++++++++++++++++++---------
 1 file changed, 27 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index d87a8ab51510..95e3bcedd33d 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -817,25 +817,39 @@ ep_config (struct ep_data *data, const char *buf, size_t len)
 static int
 ep_open (struct inode *inode, struct file *fd)
 {
-	struct ep_data		*data = inode->i_private;
-	int			value = -EBUSY;
+	struct dev_data *dev = inode->i_sb->s_fs_info;
+	struct ep_data *data;
+	int value = -ENODEV;
+
+	spin_lock_irq (&dev->lock);
+	if (dev->state == STATE_DEV_UNBOUND) {
+		spin_unlock_irq (&dev->lock);
+		return -ENOENT;
+	}
+	data = inode->i_private;
+	get_ep (data);
+	spin_unlock_irq (&dev->lock);
 
-	if (mutex_lock_interruptible(&data->lock) != 0)
+	if (mutex_lock_interruptible(&data->lock) != 0) {
+		put_ep (data);
 		return -EINTR;
-	spin_lock_irq (&data->dev->lock);
-	if (data->dev->state == STATE_DEV_UNBOUND)
+	}
+
+	value = -EBUSY;
+	spin_lock_irq (&dev->lock);
+	if (dev->state == STATE_DEV_UNBOUND)
 		value = -ENOENT;
 	else if (data->state == STATE_EP_DISABLED) {
 		value = 0;
 		data->state = STATE_EP_READY;
-		get_ep (data);
 		fd->private_data = data;
-		VDEBUG (data->dev, "%s ready\n", data->name);
+		VDEBUG (dev, "%s ready\n", data->name);
 	} else
-		DBG (data->dev, "%s state %d\n",
-			data->name, data->state);
-	spin_unlock_irq (&data->dev->lock);
+		DBG (dev, "%s state %d\n", data->name, data->state);
+	spin_unlock_irq (&dev->lock);
 	mutex_unlock(&data->lock);
+	if (value)
+		put_ep (data);
 	return value;
 }
 
@@ -1632,6 +1646,9 @@ static int activate_ep_files (struct dev_data *dev)
 	kfree (data);
 enomem0:
 	DBG (dev, "%s enomem\n", __func__);
+	spin_lock_irq (&dev->lock);
+	dev->state = STATE_DEV_UNBOUND;
+	spin_unlock_irq (&dev->lock);
 	destroy_ep_files (dev);
 	return -ENOMEM;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Forwarded: [PATCH] usb: gadgetfs: fix use-after-free in ep_open()
  2026-07-31  1:28 [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
  2026-07-31  4:26 ` Forwarded: [PATCH] usb: gadgetfs: fix use-after-free in ep_open() syzbot
@ 2026-07-31  4:44 ` syzbot
  2026-07-31  8:09 ` syzbot
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: syzbot @ 2026-07-31  4:44 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: [PATCH] usb: gadgetfs: fix use-after-free in ep_open()
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci


ep_open() dereferenced inode->i_private and locked its embedded
mutex before checking whether the underlying ep_data was still
alive. destroy_ep_files(), called from gadgetfs_unbind(), can free
that same ep_data concurrently, since nothing prevented an in-flight
open() from racing the teardown. KASAN reports a slab-use-after-free
read inside __mutex_lock_common() from ep_open(), with the object
freed by a concurrent gadgetfs_unbind() -> destroy_ep_files() ->
put_ep() -> kfree().

This race was identified by Al Viro on LKML in 2006 ("races in
drivers/usb/gadget/inode.c") but never fixed in ep_open() itself.

Fix it by checking dev->state and reading inode->i_private only
under dev->lock, and pinning the result with get_ep() before
dev->lock is dropped and before data->lock is touched. dev is
reached via the file-scope singleton the_device, which stays valid
for the duration of any open() in progress, so no dereference of
ep_data happens before its liveness is confirmed.

This depends on dev->state being set to STATE_DEV_UNBOUND under
dev->lock before destroy_ep_files() is called. gadgetfs_unbind()
already does this; activate_ep_files()'s enomem0 cleanup path did
not, leaving the same race open on the bind-failure path. This patch
adds the missing state transition there too.

Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 drivers/usb/gadget/legacy/inode.c | 40 +++++++++++++++++++++----------
 1 file changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index d87a8ab51510..0d0989d79020 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -235,6 +235,7 @@ static void put_ep (struct ep_data *data)
 
 static const char *CHIP;
 static DEFINE_MUTEX(sb_mutex);		/* Serialize superblock operations */
+static struct dev_data *the_device;
 
 /*----------------------------------------------------------------------*/
 
@@ -817,25 +818,39 @@ ep_config (struct ep_data *data, const char *buf, size_t len)
 static int
 ep_open (struct inode *inode, struct file *fd)
 {
-	struct ep_data		*data = inode->i_private;
-	int			value = -EBUSY;
+	struct dev_data *dev = the_device;
+	struct ep_data *data;
+	int value = -ENODEV;
+
+	spin_lock_irq (&dev->lock);
+	if (dev->state == STATE_DEV_UNBOUND) {
+		spin_unlock_irq (&dev->lock);
+		return -ENOENT;
+	}
+	data = inode->i_private;
+	get_ep (data);
+	spin_unlock_irq (&dev->lock);
 
-	if (mutex_lock_interruptible(&data->lock) != 0)
+	if (mutex_lock_interruptible(&data->lock) != 0) {
+		put_ep (data);
 		return -EINTR;
-	spin_lock_irq (&data->dev->lock);
-	if (data->dev->state == STATE_DEV_UNBOUND)
+	}
+
+	value = -EBUSY;
+	spin_lock_irq (&dev->lock);
+	if (dev->state == STATE_DEV_UNBOUND)
 		value = -ENOENT;
 	else if (data->state == STATE_EP_DISABLED) {
 		value = 0;
 		data->state = STATE_EP_READY;
-		get_ep (data);
 		fd->private_data = data;
-		VDEBUG (data->dev, "%s ready\n", data->name);
+		VDEBUG (dev, "%s ready\n", data->name);
 	} else
-		DBG (data->dev, "%s state %d\n",
-			data->name, data->state);
-	spin_unlock_irq (&data->dev->lock);
+		DBG (dev, "%s state %d\n", data->name, data->state);
+	spin_unlock_irq (&dev->lock);
 	mutex_unlock(&data->lock);
+	if (value)
+		put_ep (data);
 	return value;
 }
 
@@ -1632,6 +1647,9 @@ static int activate_ep_files (struct dev_data *dev)
 	kfree (data);
 enomem0:
 	DBG (dev, "%s enomem\n", __func__);
+	spin_lock_irq (&dev->lock);
+	dev->state = STATE_DEV_UNBOUND;
+	spin_unlock_irq (&dev->lock);
 	destroy_ep_files (dev);
 	return -ENOMEM;
 }
@@ -1663,8 +1681,6 @@ gadgetfs_unbind (struct usb_gadget *gadget)
 	put_dev (dev);
 }
 
-static struct dev_data		*the_device;
-
 static int gadgetfs_bind(struct usb_gadget *gadget,
 		struct usb_gadget_driver *driver)
 {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
       [not found] <20260731042637.9137-1-kartikey406@gmail.com>
@ 2026-07-31  5:42 ` syzbot
  0 siblings, 0 replies; 13+ messages in thread
From: syzbot @ 2026-07-31  5:42 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
BUG: unable to handle kernel paging request in ep_open

Unable to handle kernel paging request at virtual address dfff800000000003
KASAN: null-ptr-deref in range [0x0000000000000018-0x000000000000001f]
Mem abort info:
  ESR = 0x0000000096000005
  EC = 0x25: DABT (current EL), IL = 32 bits
  SET = 0, FnV = 0
  EA = 0, S1PTW = 0
  FSC = 0x05: level 1 translation fault
Data abort info:
  ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
  CM = 0, WnR = 0, TnD = 0, TagAccess = 0
  GCS = 0, Overlay = 0, DirtyBit = 0
[dfff800000000003] address between user and kernel address ranges
Internal error: Oops: 0000000096000005 [#1]  SMP
Modules linked in:
CPU: 0 UID: 0 PID: 5115 Comm: syz-executor Not tainted syzkaller #0 PREEMPT 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/02/2026
pstate: 234000c5 (nzCv daIF +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
pc : kasan_byte_accessible+0x10/0x20 mm/kasan/generic.c:210
lr : __kasan_check_byte+0x20/0x54 mm/kasan/common.c:573
sp : ffff800092f37660
x29: ffff800092f37660 x28: ffff800088b0a000 x27: ffff0000c79d57c0
x26: a6d980008690513c x25: 0000000000000000 x24: 0000000000000001
x23: 0000000000000000 x22: 0000000000000018 x21: 0000000000000018
x20: 0000000000000000 x19: ffff80008690513c x18: 0000000000000000
x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
x14: 00000000ffff8000 x13: 0000000000000001 x12: 0000000000000000
x11: ffff800080156ee8 x10: 0000000000000003 x9 : dfff800000000000
x8 : 0000000000000003 x7 : 0000000000000000 x6 : ffff8000836dc930
x5 : 0000000000000000 x4 : 0000000000000001 x3 : 0000000000000000
x2 : 0000000000000000 x1 : ffff80008690513c x0 : 0000000000000018
Call trace:
 kasan_mem_to_shadow include/linux/kasan.h:65 [inline] (P)
 kasan_byte_accessible+0x10/0x20 mm/kasan/generic.c:210 (P)
 kasan_check_byte include/linux/kasan.h:402 [inline]
 lock_acquire+0xa4/0x364 kernel/locking/lockdep.c:5842
 __raw_spin_lock_irq include/linux/spinlock_api_smp.h:142 [inline]
 _raw_spin_lock_irq+0x58/0x70 kernel/locking/spinlock.c:174
 spin_lock_irq include/linux/spinlock.h:372 [inline]
 ep_open+0x70/0x2ec drivers/usb/gadget/legacy/inode.c:824
 do_dentry_open+0x5c4/0xfc0 fs/open.c:947
 vfs_open+0x44/0x2dc fs/open.c:1052
 do_open fs/namei.c:4700 [inline]
 path_openat+0x21fc/0x2a60 fs/namei.c:4863
 do_file_open+0x1c8/0x2e8 fs/namei.c:4892
 do_sys_openat2+0x114/0x1e8 fs/open.c:1368
 do_sys_open+0xb0/0xe0 fs/open.c:1374
 __do_sys_openat fs/open.c:1390 [inline]
 __se_sys_openat fs/open.c:1385 [inline]
 __arm64_sys_openat+0xa0/0xbc fs/open.c:1385
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x64/0x260 arch/arm64/kernel/entry-common.c:736
 el0t_64_sync_handler+0x48/0x148 arch/arm64/kernel/entry-common.c:755
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:594
Code: d503245f d343fc08 d2d00009 f2fbffe9 (38696908) 
---[ end trace 0000000000000000 ]---
----------------
Code disassembly (best guess):
   0:	d503245f 	bti	c
   4:	d343fc08 	lsr	x8, x0, #3
   8:	d2d00009 	mov	x9, #0x800000000000        	// #140737488355328
   c:	f2fbffe9 	movk	x9, #0xdfff, lsl #48
* 10:	38696908 	ldrb	w8, [x8, x9] <-- trapping instruction


Tested on:

commit:         365f9c7a Merge branches 'for-next/core' and 'for-next/..
git tree:       git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
console output: https://syzkaller.appspot.com/x/log.txt?x=174c8c9e580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=72c97575381cec47
dashboard link: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
compiler:       Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
userspace arch: arm64
patch:          https://syzkaller.appspot.com/x/patch.diff?x=1176caea580000


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
       [not found] <20260731044451.10817-1-kartikey406@gmail.com>
@ 2026-07-31  6:59 ` syzbot
  0 siblings, 0 replies; 13+ messages in thread
From: syzbot @ 2026-07-31  6:59 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
KASAN: slab-use-after-free Write in ep_open

==================================================================
BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 [inline]
BUG: KASAN: slab-use-after-free in atomic_fetch_add_relaxed include/linux/atomic/atomic-instrumented.h:252 [inline]
BUG: KASAN: slab-use-after-free in __refcount_add include/linux/refcount.h:283 [inline]
BUG: KASAN: slab-use-after-free in __refcount_inc include/linux/refcount.h:366 [inline]
BUG: KASAN: slab-use-after-free in refcount_inc include/linux/refcount.h:383 [inline]
BUG: KASAN: slab-use-after-free in get_ep drivers/usb/gadget/legacy/inode.c:214 [inline]
BUG: KASAN: slab-use-after-free in ep_open+0xb8/0x2bc drivers/usb/gadget/legacy/inode.c:831
Write of size 4 at addr ffff0000d322748c by task syz-executor/5557

CPU: 1 UID: 0 PID: 5557 Comm: syz-executor Not tainted syzkaller #0 PREEMPT 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/02/2026
Call trace:
 show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:499 (C)
 __dump_stack+0x30/0x40 lib/dump_stack.c:94
 dump_stack_lvl+0xd8/0x12c lib/dump_stack.c:120
 print_address_description+0xb0/0x238 mm/kasan/report.c:378
 print_report+0x68/0x84 mm/kasan/report.c:482
 kasan_report+0x8c/0xc4 mm/kasan/report.c:595
 check_region_inline mm/kasan/generic.c:-1 [inline]
 kasan_check_range+0x17c/0x1ac mm/kasan/generic.c:200
 __kasan_check_write+0x20/0x30 mm/kasan/shadow.c:37
 instrument_atomic_read_write include/linux/instrumented.h:112 [inline]
 atomic_fetch_add_relaxed include/linux/atomic/atomic-instrumented.h:252 [inline]
 __refcount_add include/linux/refcount.h:283 [inline]
 __refcount_inc include/linux/refcount.h:366 [inline]
 refcount_inc include/linux/refcount.h:383 [inline]
 get_ep drivers/usb/gadget/legacy/inode.c:214 [inline]
 ep_open+0xb8/0x2bc drivers/usb/gadget/legacy/inode.c:831
 do_dentry_open+0x5c4/0xfc0 fs/open.c:947
 vfs_open+0x44/0x2dc fs/open.c:1052
 do_open fs/namei.c:4700 [inline]
 path_openat+0x21fc/0x2a60 fs/namei.c:4863
 do_file_open+0x1c8/0x2e8 fs/namei.c:4892
 do_sys_openat2+0x114/0x1e8 fs/open.c:1368
 do_sys_open+0xb0/0xe0 fs/open.c:1374
 __do_sys_openat fs/open.c:1390 [inline]
 __se_sys_openat fs/open.c:1385 [inline]
 __arm64_sys_openat+0xa0/0xbc fs/open.c:1385
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x64/0x260 arch/arm64/kernel/entry-common.c:736
 el0t_64_sync_handler+0x48/0x148 arch/arm64/kernel/entry-common.c:755
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:594

Allocated by task 5798:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x40/0x78 mm/kasan/common.c:78
 kasan_save_alloc_info+0x44/0x54 mm/kasan/generic.c:570
 poison_kmalloc_redzone mm/kasan/common.c:398 [inline]
 __kasan_kmalloc+0x9c/0xb4 mm/kasan/common.c:415
 kasan_kmalloc include/linux/kasan.h:263 [inline]
 __kmalloc_cache_noprof+0x2e8/0x5ec mm/slub.c:5515
 _kmalloc_noprof include/linux/slab.h:969 [inline]
 _kzalloc_noprof include/linux/slab.h:1290 [inline]
 activate_ep_files drivers/usb/gadget/legacy/inode.c:1616 [inline]
 gadgetfs_bind+0x204/0x7a0 drivers/usb/gadget/legacy/inode.c:1708
 gadget_bind_driver+0x274/0x834 drivers/usb/gadget/udc/core.c:1662
 call_driver_probe drivers/base/dd.c:-1 [inline]
 really_probe+0x29c/0x800 drivers/base/dd.c:706
 __driver_probe_device+0x1e0/0x350 drivers/base/dd.c:868
 driver_probe_device+0x6c/0x19c drivers/base/dd.c:898
 __driver_attach+0x168/0x384 drivers/base/dd.c:1292
 bus_for_each_dev+0x128/0x1b4 drivers/base/bus.c:383
 driver_attach+0x50/0x60 drivers/base/dd.c:1310
 bus_add_driver+0x208/0x500 drivers/base/bus.c:763
 driver_register+0x220/0x310 drivers/base/driver.c:174
 usb_gadget_register_driver_owner+0xf0/0x25c drivers/usb/gadget/udc/core.c:1752
 dev_config+0x91c/0xcc0 drivers/usb/gadget/legacy/inode.c:1899
 vfs_write+0x2a4/0xa0c fs/read_write.c:685
 ksys_write+0x12c/0x228 fs/read_write.c:739
 __do_sys_write fs/read_write.c:750 [inline]
 __se_sys_write fs/read_write.c:747 [inline]
 __arm64_sys_write+0x7c/0x90 fs/read_write.c:747
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x64/0x260 arch/arm64/kernel/entry-common.c:736
 el0t_64_sync_handler+0x48/0x148 arch/arm64/kernel/entry-common.c:755
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:594

Freed by task 5799:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x40/0x78 mm/kasan/common.c:78
 kasan_save_free_info+0x58/0x70 mm/kasan/generic.c:584
 poison_slab_object mm/kasan/common.c:253 [inline]
 __kasan_slab_free+0x74/0xa4 mm/kasan/common.c:285
 kasan_slab_free include/linux/kasan.h:235 [inline]
 slab_free_hook mm/slub.c:2705 [inline]
 slab_free mm/slub.c:6405 [inline]
 kfree+0x188/0x690 mm/slub.c:6720
 put_ep+0xd0/0x144 drivers/usb/gadget/legacy/inode.c:225
 destroy_ep_files+0x244/0x2dc drivers/usb/gadget/legacy/inode.c:1597
 gadgetfs_unbind+0x114/0x1f0 drivers/usb/gadget/legacy/inode.c:1673
 gadget_unbind_driver+0x188/0x790 drivers/usb/gadget/udc/core.c:1724
 device_remove+0xc4/0x134 drivers/base/dd.c:616
 __device_release_driver drivers/base/dd.c:1349 [inline]
 device_release_driver_internal+0x124/0x20c drivers/base/dd.c:1372
 driver_detach+0x124/0x1b4 drivers/base/dd.c:1435
 bus_remove_driver+0x124/0x22c drivers/base/bus.c:832
 driver_unregister+0x78/0xac drivers/base/driver.c:202
 usb_gadget_unregister_driver+0x50/0x78 drivers/usb/gadget/udc/core.c:1784
 dev_release+0x8c/0x15c drivers/usb/gadget/legacy/inode.c:1213
 __fput+0x338/0x74c fs/file_table.c:512
 ____fput+0x20/0x30 fs/file_table.c:540
 task_work_run+0x1cc/0x25c kernel/task_work.c:233
 exit_task_work include/linux/task_work.h:40 [inline]
 do_exit+0x58c/0x1a74 kernel/exit.c:1009
 __do_sys_exit kernel/exit.c:1119 [inline]
 __se_sys_exit kernel/exit.c:1117 [inline]
 do_group_exit+0x0/0x238 kernel/exit.c:1117
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x64/0x260 arch/arm64/kernel/entry-common.c:736
 el0t_64_sync_handler+0x48/0x148 arch/arm64/kernel/entry-common.c:755
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:594

The buggy address belongs to the object at ffff0000d3227400
 which belongs to the cache kmalloc-512 of size 512
The buggy address is located 140 bytes inside of
 freed 512-byte region [ffff0000d3227400, ffff0000d3227600)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x113224
head: order:2 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x5ffc00000000040(head|node=0|zone=2|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 05ffc00000000040 ffff0000c0001c80 dead000000000100 dead000000000122
raw: 0000000000000000 0000000800100010 00000000f5000000 0000000000000000
head: 05ffc00000000040 ffff0000c0001c80 dead000000000100 dead000000000122
head: 0000000000000000 0000000800100010 00000000f5000000 0000000000000000
head: 05ffc00000000002 fffffdffc34c8901 00000000ffffffff 00000000ffffffff
head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000004
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff0000d3227380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff0000d3227400: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff0000d3227480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                      ^
 ffff0000d3227500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff0000d3227580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================
------------[ cut here ]------------
refcount_t: addition on 0; use-after-free.
WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x134/0x1f8 lib/refcount.c:25, CPU#1: syz-executor/5557
Modules linked in:
CPU: 1 UID: 0 PID: 5557 Comm: syz-executor Tainted: G    B               syzkaller #0 PREEMPT 
Tainted: [B]=BAD_PAGE
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/02/2026
pstate: 634000c5 (nZCv daIF +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
pc : refcount_warn_saturate+0x134/0x1f8 lib/refcount.c:25
lr : refcount_warn_saturate+0x134/0x1f8 lib/refcount.c:25
sp : ffff800094a97740
x29: ffff800094a97740 x28: dfff800000000000 x27: 1fffe00019788600
x26: ffff0000cbc43008 x25: 1fffe0001aebd509 x24: ffff0000d75ea848
x23: dfff800000000000 x22: 0000000000000000 x21: ffff0000cbc42fc0
x20: ffff0000d322748c x19: ffff80008a158000 x18: 0000000000000000
x17: 3d3d3d3d3d3d3d3d x16: 3d3d3d3d3d3d3d3d x15: 3d3d3d3d3d3d3d3d
x14: 3d3d3d3d3d3d3d3d x13: 0000000000000001 x12: 0000000000000000
x11: 0000000000000000 x10: 0000000000000003 x9 : 360a90020a0ce000
x8 : 360a90020a0ce000 x7 : 0000000000000001 x6 : ffff80008048de94
x5 : 0000000000000000 x4 : 0000000000000000 x3 : ffff8000802f8054
x2 : 0000000100000001 x1 : ffff0000c2a03a80 x0 : 0000000000000000
Call trace:
 refcount_warn_saturate+0x134/0x1f8 lib/refcount.c:25 (P)
 __refcount_add include/linux/refcount.h:-1 [inline]
 __refcount_inc include/linux/refcount.h:366 [inline]
 refcount_inc include/linux/refcount.h:383 [inline]
 get_ep drivers/usb/gadget/legacy/inode.c:214 [inline]
 ep_open+0x238/0x2bc drivers/usb/gadget/legacy/inode.c:831
 do_dentry_open+0x5c4/0xfc0 fs/open.c:947
 vfs_open+0x44/0x2dc fs/open.c:1052
 do_open fs/namei.c:4700 [inline]
 path_openat+0x21fc/0x2a60 fs/namei.c:4863
 do_file_open+0x1c8/0x2e8 fs/namei.c:4892
 do_sys_openat2+0x114/0x1e8 fs/open.c:1368
 do_sys_open+0xb0/0xe0 fs/open.c:1374
 __do_sys_openat fs/open.c:1390 [inline]
 __se_sys_openat fs/open.c:1385 [inline]
 __arm64_sys_openat+0xa0/0xbc fs/open.c:1385
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x64/0x260 arch/arm64/kernel/entry-common.c:736
 el0t_64_sync_handler+0x48/0x148 arch/arm64/kernel/entry-common.c:755
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:594
irq event stamp: 217440
hardirqs last  enabled at (217439): [<ffff800080b9d9d8>] kasan_quarantine_put+0xb4/0x1c4 mm/kasan/quarantine.c:234
hardirqs last disabled at (217440): [<ffff8000869050fc>] __raw_spin_lock_irq include/linux/spinlock_api_smp.h:140 [inline]
hardirqs last disabled at (217440): [<ffff8000869050fc>] _raw_spin_lock_irq+0x28/0x70 kernel/locking/spinlock.c:174
softirqs last  enabled at (213442): [<ffff80008013c0b4>] local_bh_enable include/linux/bottom_half.h:33 [inline]
softirqs last  enabled at (213442): [<ffff80008013c0b4>] put_cpu_fpsimd_context arch/arm64/kernel/fpsimd.c:251 [inline]
softirqs last  enabled at (213442): [<ffff80008013c0b4>] fpsimd_restore_current_state+0x39c/0x9c8 arch/arm64/kernel/fpsimd.c:1797
softirqs last disabled at (213440): [<ffff80008013bd5c>] local_bh_disable include/linux/bottom_half.h:20 [inline]
softirqs last disabled at (213440): [<ffff80008013bd5c>] get_cpu_fpsimd_context arch/arm64/kernel/fpsimd.c:234 [inline]
softirqs last disabled at (213440): [<ffff80008013bd5c>] fpsimd_restore_current_state+0x44/0x9c8 arch/arm64/kernel/fpsimd.c:1790
---[ end trace 0000000000000000 ]---


Tested on:

commit:         365f9c7a Merge branches 'for-next/core' and 'for-next/..
git tree:       git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
console output: https://syzkaller.appspot.com/x/log.txt?x=114978c6580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=72c97575381cec47
dashboard link: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
compiler:       Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
userspace arch: arm64
patch:          https://syzkaller.appspot.com/x/patch.diff?x=12b475b9580000


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Forwarded: [PATCH] usb: gadgetfs: fix use-after-free in ep_open()
  2026-07-31  1:28 [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
  2026-07-31  4:26 ` Forwarded: [PATCH] usb: gadgetfs: fix use-after-free in ep_open() syzbot
  2026-07-31  4:44 ` syzbot
@ 2026-07-31  8:09 ` syzbot
  2026-07-31 11:40 ` Forwarded: [PATCH v2] " syzbot
  2026-08-17 13:42 ` [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
  4 siblings, 0 replies; 13+ messages in thread
From: syzbot @ 2026-07-31  8:09 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: [PATCH] usb: gadgetfs: fix use-after-free in ep_open()
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci


ep_open() dereferenced inode->i_private and locked its embedded
mutex before checking whether the underlying ep_data was still
alive. destroy_ep_files(), called from gadgetfs_unbind(), can free
that same ep_data concurrently, since nothing prevented an in-flight
open() from racing the teardown. KASAN reports a slab-use-after-free
in ep_open(), with the object freed by a concurrent gadgetfs_unbind()
-> destroy_ep_files() -> put_ep() -> kfree().

This race was identified by Al Viro on LKML in 2006 ("races in
drivers/usb/gadget/inode.c"), including the fix direction, but it
was never applied to ep_open() itself.

Fix it as originally suggested: add an inode back-pointer to
ep_data, have destroy_ep_files() clear inode->i_private to NULL
under dev->lock before the object can be freed, and have ep_open()
read inode->i_private and pin the result with get_ep() under that
same lock, bailing out with -ENOENT if it finds NULL. This makes
liveness self-evident at the point of use instead of being inferred
from device state, so it holds regardless of which path frees the
endpoint.

gadgetfs_create_file() gains an optional inode-out parameter so
activate_ep_files() can capture the inode it creates; the ep0 caller
in gadgetfs_fill_super() passes NULL, since dev_data is unaffected
by this fix.

Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 drivers/usb/gadget/legacy/inode.c | 51 +++++++++++++++++++++----------
 1 file changed, 35 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index d87a8ab51510..f566b2ec7c38 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -207,6 +207,7 @@ struct ep_data {
 	struct usb_endpoint_descriptor	desc, hs_desc;
 	struct list_head		epfiles;
 	wait_queue_head_t		wait;
+	struct inode                    *inode;
 };
 
 static inline void get_ep (struct ep_data *data)
@@ -235,6 +236,7 @@ static void put_ep (struct ep_data *data)
 
 static const char *CHIP;
 static DEFINE_MUTEX(sb_mutex);		/* Serialize superblock operations */
+static struct dev_data *the_device;
 
 /*----------------------------------------------------------------------*/
 
@@ -817,25 +819,39 @@ ep_config (struct ep_data *data, const char *buf, size_t len)
 static int
 ep_open (struct inode *inode, struct file *fd)
 {
-	struct ep_data		*data = inode->i_private;
-	int			value = -EBUSY;
+	struct dev_data *dev = the_device;
+	struct ep_data *data;
+	int value = -ENODEV;
+
+	spin_lock_irq (&dev->lock);
+	data = inode->i_private;
+	if (data == NULL) {
+		spin_unlock_irq (&dev->lock);
+		return -ENOENT;
+	}
+	get_ep (data);
+	spin_unlock_irq (&dev->lock);
 
-	if (mutex_lock_interruptible(&data->lock) != 0)
+	if (mutex_lock_interruptible(&data->lock) != 0) {
+		put_ep (data);
 		return -EINTR;
-	spin_lock_irq (&data->dev->lock);
-	if (data->dev->state == STATE_DEV_UNBOUND)
+	}
+
+	value = -EBUSY;
+	spin_lock_irq (&dev->lock);
+	if (dev->state == STATE_DEV_UNBOUND)
 		value = -ENOENT;
 	else if (data->state == STATE_EP_DISABLED) {
 		value = 0;
 		data->state = STATE_EP_READY;
-		get_ep (data);
 		fd->private_data = data;
-		VDEBUG (data->dev, "%s ready\n", data->name);
+		VDEBUG (dev, "%s ready\n", data->name);
 	} else
-		DBG (data->dev, "%s state %d\n",
-			data->name, data->state);
-	spin_unlock_irq (&data->dev->lock);
+		DBG (dev, "%s state %d\n", data->name, data->state);
+	spin_unlock_irq (&dev->lock);
 	mutex_unlock(&data->lock);
+	if (value)
+		put_ep (data);
 	return value;
 }
 
@@ -1563,6 +1579,7 @@ static void destroy_ep_files (struct dev_data *dev)
 		/* break link to FS */
 		ep = list_first_entry (&dev->epfiles, struct ep_data, epfiles);
 		list_del_init (&ep->epfiles);
+		ep->inode->i_private = NULL;
 		spin_unlock_irq (&dev->lock);
 
 		/* break link to controller */
@@ -1588,7 +1605,8 @@ static void destroy_ep_files (struct dev_data *dev)
 
 
 static int gadgetfs_create_file (struct super_block *sb, char const *name,
-		void *data, const struct file_operations *fops);
+		void *data, const struct file_operations *fops,
+                struct inode **inode_out);
 
 static int activate_ep_files (struct dev_data *dev)
 {
@@ -1618,7 +1636,7 @@ static int activate_ep_files (struct dev_data *dev)
 			goto enomem1;
 
 		err = gadgetfs_create_file (dev->sb, data->name,
-				data, &ep_io_operations);
+				data, &ep_io_operations, &data->inode);
 		if (err)
 			goto enomem2;
 		list_add_tail (&data->epfiles, &dev->epfiles);
@@ -1663,8 +1681,6 @@ gadgetfs_unbind (struct usb_gadget *gadget)
 	put_dev (dev);
 }
 
-static struct dev_data		*the_device;
-
 static int gadgetfs_bind(struct usb_gadget *gadget,
 		struct usb_gadget_driver *driver)
 {
@@ -1984,7 +2000,7 @@ gadgetfs_make_inode (struct super_block *sb,
  * so inode and dentry are paired, until device reconfig.
  */
 static int gadgetfs_create_file (struct super_block *sb, char const *name,
-		void *data, const struct file_operations *fops)
+		void *data, const struct file_operations *fops, struct inode **inode_out)
 {
 	struct dentry	*dentry;
 	struct inode	*inode;
@@ -1994,6 +2010,9 @@ static int gadgetfs_create_file (struct super_block *sb, char const *name,
 	if (!inode)
 		return -ENOMEM;
 
+	if(inode_out)
+		*inode_out = inode;
+
 	dentry = simple_start_creating(sb->s_root, name);
 	if (IS_ERR(dentry)) {
 		iput(inode);
@@ -2056,7 +2075,7 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
 		goto Enomem;
 
 	dev->sb = sb;
-	rc = gadgetfs_create_file(sb, CHIP, dev, &ep0_operations);
+	rc = gadgetfs_create_file(sb, CHIP, dev, &ep0_operations, NULL);
 	if (rc) {
 		put_dev(dev);
 		goto Enomem;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
       [not found] <20260731080941.13394-1-kartikey406@gmail.com>
@ 2026-07-31  9:08 ` syzbot
  0 siblings, 0 replies; 13+ messages in thread
From: syzbot @ 2026-07-31  9:08 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
Tested-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com

Tested on:

commit:         365f9c7a Merge branches 'for-next/core' and 'for-next/..
git tree:       git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
console output: https://syzkaller.appspot.com/x/log.txt?x=14c75499580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=72c97575381cec47
dashboard link: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
compiler:       Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
userspace arch: arm64
patch:          https://syzkaller.appspot.com/x/patch.diff?x=152a75b9580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Forwarded: [PATCH v2] usb: gadgetfs: fix use-after-free in ep_open()
  2026-07-31  1:28 [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
                   ` (2 preceding siblings ...)
  2026-07-31  8:09 ` syzbot
@ 2026-07-31 11:40 ` syzbot
  2026-08-17 13:42 ` [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
  4 siblings, 0 replies; 13+ messages in thread
From: syzbot @ 2026-07-31 11:40 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: [PATCH v2] usb: gadgetfs: fix use-after-free in ep_open()
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci


ep_open() dereferenced inode->i_private and locked its embedded
mutex before checking whether the underlying ep_data was still
alive. destroy_ep_files(), called from gadgetfs_unbind(), can free
that same ep_data concurrently, since nothing prevented an in-flight
open() from racing the teardown. KASAN reports a slab-use-after-free
in ep_open(), with the object freed by a concurrent gadgetfs_unbind()
-> destroy_ep_files() -> put_ep() -> kfree().

Fix it by adding an inode back-pointer to ep_data, having
destroy_ep_files() clear inode->i_private to NULL under dev->lock
before the object can be freed, and having ep_open() read
inode->i_private and pin the result with get_ep() under that same
lock, bailing out with -ENOENT if it finds NULL. This makes liveness
self-evident at the point of use instead of being inferred from
device state, so it holds regardless of which path frees the
endpoint.

dev is derived from inode->i_sb->s_fs_info, set in
gadgetfs_fill_super(), rather than from the file's the_device
singleton, so ep_open() is correctly scoped to the specific mount
the inode belongs to.

gadgetfs_create_file() now returns the created inode (or an
ERR_PTR) directly instead of taking an output parameter, so
activate_ep_files() can store it in data->inode without an
unexplained NULL at call sites that don't need it.

Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
Fixes: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 ("Linux-2.6.12-rc2")
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
v2:
 - Added Fixes: tag; git blame traces the bug to the 2005 git
   import boundary, confirmed no later commit changed the ordering
 - Derive dev from inode->i_sb->s_fs_info instead of the new
   the_device singleton, so the lookup is scoped to the inode's
   own mount instead of a global (Greg)
 - gadgetfs_create_file() now returns struct inode * / ERR_PTR
   instead of taking an inode_out output parameter, so call sites
   don't need an unexplained NULL argument (Greg)
---
 drivers/usb/gadget/legacy/inode.c | 61 ++++++++++++++++++++-----------
 1 file changed, 39 insertions(+), 22 deletions(-)

diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index d87a8ab51510..e5a316777db2 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -207,6 +207,7 @@ struct ep_data {
 	struct usb_endpoint_descriptor	desc, hs_desc;
 	struct list_head		epfiles;
 	wait_queue_head_t		wait;
+	struct inode                    *inode;
 };
 
 static inline void get_ep (struct ep_data *data)
@@ -235,6 +236,7 @@ static void put_ep (struct ep_data *data)
 
 static const char *CHIP;
 static DEFINE_MUTEX(sb_mutex);		/* Serialize superblock operations */
+static struct dev_data *the_device;
 
 /*----------------------------------------------------------------------*/
 
@@ -817,25 +819,39 @@ ep_config (struct ep_data *data, const char *buf, size_t len)
 static int
 ep_open (struct inode *inode, struct file *fd)
 {
-	struct ep_data		*data = inode->i_private;
-	int			value = -EBUSY;
+	struct dev_data *dev = inode->i_sb->s_fs_info;
+	struct ep_data *data;
+	int value = -ENODEV;
+
+	spin_lock_irq (&dev->lock);
+	data = inode->i_private;
+	if (data == NULL) {
+		spin_unlock_irq (&dev->lock);
+		return -ENOENT;
+	}
+	get_ep (data);
+	spin_unlock_irq (&dev->lock);
 
-	if (mutex_lock_interruptible(&data->lock) != 0)
+	if (mutex_lock_interruptible(&data->lock) != 0) {
+		put_ep (data);
 		return -EINTR;
-	spin_lock_irq (&data->dev->lock);
-	if (data->dev->state == STATE_DEV_UNBOUND)
+	}
+
+	value = -EBUSY;
+	spin_lock_irq (&dev->lock);
+	if (dev->state == STATE_DEV_UNBOUND)
 		value = -ENOENT;
 	else if (data->state == STATE_EP_DISABLED) {
 		value = 0;
 		data->state = STATE_EP_READY;
-		get_ep (data);
 		fd->private_data = data;
-		VDEBUG (data->dev, "%s ready\n", data->name);
+		VDEBUG (dev, "%s ready\n", data->name);
 	} else
-		DBG (data->dev, "%s state %d\n",
-			data->name, data->state);
-	spin_unlock_irq (&data->dev->lock);
+		DBG (dev, "%s state %d\n", data->name, data->state);
+	spin_unlock_irq (&dev->lock);
 	mutex_unlock(&data->lock);
+	if (value)
+		put_ep (data);
 	return value;
 }
 
@@ -1563,6 +1579,7 @@ static void destroy_ep_files (struct dev_data *dev)
 		/* break link to FS */
 		ep = list_first_entry (&dev->epfiles, struct ep_data, epfiles);
 		list_del_init (&ep->epfiles);
+		ep->inode->i_private = NULL;
 		spin_unlock_irq (&dev->lock);
 
 		/* break link to controller */
@@ -1587,14 +1604,13 @@ static void destroy_ep_files (struct dev_data *dev)
 }
 
 
-static int gadgetfs_create_file (struct super_block *sb, char const *name,
+static struct inode *gadgetfs_create_file (struct super_block *sb, char const *name,
 		void *data, const struct file_operations *fops);
 
 static int activate_ep_files (struct dev_data *dev)
 {
 	struct usb_ep	*ep;
 	struct ep_data	*data;
-	int err;
 
 	gadget_for_each_ep (ep, dev->gadget) {
 
@@ -1617,9 +1633,9 @@ static int activate_ep_files (struct dev_data *dev)
 		if (!data->req)
 			goto enomem1;
 
-		err = gadgetfs_create_file (dev->sb, data->name,
+		data->inode = gadgetfs_create_file (dev->sb, data->name,
 				data, &ep_io_operations);
-		if (err)
+		if (IS_ERR(data->inode))
 			goto enomem2;
 		list_add_tail (&data->epfiles, &dev->epfiles);
 	}
@@ -1663,8 +1679,6 @@ gadgetfs_unbind (struct usb_gadget *gadget)
 	put_dev (dev);
 }
 
-static struct dev_data		*the_device;
-
 static int gadgetfs_bind(struct usb_gadget *gadget,
 		struct usb_gadget_driver *driver)
 {
@@ -1983,7 +1997,7 @@ gadgetfs_make_inode (struct super_block *sb,
 /* creates in fs root directory, so non-renamable and non-linkable.
  * so inode and dentry are paired, until device reconfig.
  */
-static int gadgetfs_create_file (struct super_block *sb, char const *name,
+static struct inode *gadgetfs_create_file (struct super_block *sb, char const *name,
 		void *data, const struct file_operations *fops)
 {
 	struct dentry	*dentry;
@@ -1992,18 +2006,18 @@ static int gadgetfs_create_file (struct super_block *sb, char const *name,
 	inode = gadgetfs_make_inode (sb, data, fops,
 			S_IFREG | (default_perm & S_IRWXUGO));
 	if (!inode)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	dentry = simple_start_creating(sb->s_root, name);
 	if (IS_ERR(dentry)) {
 		iput(inode);
-		return PTR_ERR(dentry);
+		return ERR_CAST(dentry);
 	}
 
 	d_make_persistent(dentry, inode);
 
 	simple_done_creating(dentry);
-	return 0;
+	return inode;
 }
 
 static const struct super_operations gadget_fs_operations = {
@@ -2056,8 +2070,11 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
 		goto Enomem;
 
 	dev->sb = sb;
-	rc = gadgetfs_create_file(sb, CHIP, dev, &ep0_operations);
-	if (rc) {
+	sb->s_fs_info = dev;
+	inode = gadgetfs_create_file(sb, CHIP, dev, &ep0_operations);
+	if (IS_ERR(inode)) {
+		rc = PTR_ERR(inode);
+		sb->s_fs_info = NULL;
 		put_dev(dev);
 		goto Enomem;
 	}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
       [not found] <20260731114022.18295-1-kartikey406@gmail.com>
@ 2026-07-31 16:21 ` syzbot
  0 siblings, 0 replies; 13+ messages in thread
From: syzbot @ 2026-07-31 16:21 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
Tested-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com

Tested on:

commit:         365f9c7a Merge branches 'for-next/core' and 'for-next/..
git tree:       git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
console output: https://syzkaller.appspot.com/x/log.txt?x=15bd75b9580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=72c97575381cec47
dashboard link: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
compiler:       Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
userspace arch: arm64
patch:          https://syzkaller.appspot.com/x/patch.diff?x=17a77a49580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
  2026-07-31  1:28 [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
                   ` (3 preceding siblings ...)
  2026-07-31 11:40 ` Forwarded: [PATCH v2] " syzbot
@ 2026-08-17 13:42 ` syzbot
  2026-08-17 15:04   ` Jens Axboe
  4 siblings, 1 reply; 13+ messages in thread
From: syzbot @ 2026-08-17 13:42 UTC (permalink / raw)
  To: asml.silence, axboe, brauner, gregkh, io-uring, jack, kartikey406,
	kees, linux-kernel, linux-usb, mjguzik, nogikh, stern, syzbot,
	syzbot, syzkaller-bugs, syzkaller-upstream-moderation, torvalds,
	viro

syzbot has bisected this issue to:

commit aa00f67adc2c0d6439f81b5a81ff181377c47a7e
Author: Jens Axboe <axboe@kernel.dk>
Date:   Tue Oct 22 19:47:00 2024 +0000

    io_uring: add support for fixed wait regions

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=10e60679580000
start commit:   9a143525f62b Merge tag 'ata-7.2-rc7' of git://git.kernel.o..
git tree:       upstream
final oops:     https://syzkaller.appspot.com/x/report.txt?x=12e60679580000
console output: https://syzkaller.appspot.com/x/log.txt?x=14e60679580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=c44651ea7dd2f307
dashboard link: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=120defb9580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=16323fb9580000

Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
Fixes: aa00f67adc2c ("io_uring: add support for fixed wait regions")

For information about bisection process see: https://goo.gl/tpsmEJ#bisection

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
  2026-08-17 13:42 ` [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
@ 2026-08-17 15:04   ` Jens Axboe
  2026-08-17 15:45     ` Alan Stern
  0 siblings, 1 reply; 13+ messages in thread
From: Jens Axboe @ 2026-08-17 15:04 UTC (permalink / raw)
  To: syzbot, asml.silence, brauner, gregkh, io-uring, jack,
	kartikey406, kees, linux-kernel, linux-usb, mjguzik, nogikh,
	stern, syzbot, syzbot, syzkaller-bugs,
	syzkaller-upstream-moderation, torvalds, viro

On 8/17/26 7:42 AM, syzbot wrote:
> syzbot has bisected this issue to:
> 
> commit aa00f67adc2c0d6439f81b5a81ff181377c47a7e
> Author: Jens Axboe <axboe@kernel.dk>
> Date:   Tue Oct 22 19:47:00 2024 +0000
> 
>     io_uring: add support for fixed wait regions
> 
> bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=10e60679580000
> start commit:   9a143525f62b Merge tag 'ata-7.2-rc7' of git://git.kernel.o..
> git tree:       upstream
> final oops:     https://syzkaller.appspot.com/x/report.txt?x=12e60679580000
> console output: https://syzkaller.appspot.com/x/log.txt?x=14e60679580000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=c44651ea7dd2f307
> dashboard link: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=120defb9580000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=16323fb9580000
> 
> Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
> Fixes: aa00f67adc2c ("io_uring: add support for fixed wait regions")

That looks like nonsense, I strongly suspect it's a race and hence your
bisection ends up being mostly useless as it sends you in random directions.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
  2026-08-17 15:04   ` Jens Axboe
@ 2026-08-17 15:45     ` Alan Stern
  2026-08-17 16:38       ` syzbot
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Stern @ 2026-08-17 15:45 UTC (permalink / raw)
  To: Jens Axboe
  Cc: syzbot, asml.silence, brauner, gregkh, io-uring, jack,
	kartikey406, kees, linux-kernel, linux-usb, mjguzik, nogikh,
	syzbot, syzbot, syzkaller-bugs, syzkaller-upstream-moderation,
	torvalds, viro

On Mon, Aug 17, 2026 at 09:04:06AM -0600, Jens Axboe wrote:
> On 8/17/26 7:42 AM, syzbot wrote:
> > syzbot has bisected this issue to:
> > 
> > commit aa00f67adc2c0d6439f81b5a81ff181377c47a7e
> > Author: Jens Axboe <axboe@kernel.dk>
> > Date:   Tue Oct 22 19:47:00 2024 +0000
> > 
> >     io_uring: add support for fixed wait regions
> > 
> > bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=10e60679580000
> > start commit:   9a143525f62b Merge tag 'ata-7.2-rc7' of git://git.kernel.o..
> > git tree:       upstream
> > final oops:     https://syzkaller.appspot.com/x/report.txt?x=12e60679580000
> > console output: https://syzkaller.appspot.com/x/log.txt?x=14e60679580000
> > kernel config:  https://syzkaller.appspot.com/x/.config?x=c44651ea7dd2f307
> > dashboard link: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
> > syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=120defb9580000
> > C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=16323fb9580000
> > 
> > Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
> > Fixes: aa00f67adc2c ("io_uring: add support for fixed wait regions")
> 
> That looks like nonsense, I strongly suspect it's a race and hence your
> bisection ends up being mostly useless as it sends you in random directions.

Agreed.

The patch below has already been sent to the USB mailing list.  Has 
syzbot tested it?

Alan Stern

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ v7.2

From: Aleksandr Nogikh <nogikh@google.com>

A race condition exists between opening a gadgetfs endpoint file and the
destruction of the endpoint files, leading to a use-after-free of the
ep_data object.

When an endpoint file is opened, the VFS looks up the dentry and calls
ep_open(). ep_open() retrieves the ep_data pointer from inode->i_private
and attempts to lock its mutex. Concurrently, if the gadget is unbound,
destroy_ep_files() iterates over the endpoints, unhashes their dentries,
and immediately calls put_ep(). This drops the initial reference to the
ep_data object, freeing it. If another thread is already in the process of
opening the file, it holds a reference to the dentry and the inode. The
inode remains alive, and its i_private pointer still points to the
now-freed ep_data. When ep_open() proceeds to lock data->lock, it accesses
freed memory.

BUG: KASAN: slab-use-after-free in __mutex_lock_common
kernel/locking/mutex.c:625 [inline]
BUG: KASAN: slab-use-after-free in __mutex_lock+0x130/0xf14
kernel/locking/mutex.c:821
Read of size 8 at addr ffff0000f43acc58 by task syz-executor/5900

Call trace:
 __mutex_lock_common kernel/locking/mutex.c:625 [inline]
 __mutex_lock+0x130/0xf14 kernel/locking/mutex.c:821
 mutex_lock_interruptible_nested+0x24/0x30 kernel/locking/mutex.c:899
 ep_open+0x58/0x25c drivers/usb/gadget/legacy/inode.c:823
 do_dentry_open+0x5c4/0xfc0 fs/open.c:947
 vfs_open+0x44/0x2dc fs/open.c:1052

Freed by task 6138:
 kfree+0x188/0x690 mm/slub.c:6692
 put_ep+0xd0/0x144 drivers/usb/gadget/legacy/inode.c:225
 destroy_ep_files+0x244/0x2dc drivers/usb/gadget/legacy/inode.c:1582
 gadgetfs_unbind+0x114/0x1f0 drivers/usb/gadget/legacy/inode.c:1655
 gadget_unbind_driver+0x188/0x790 drivers/usb/gadget/udc/core.c:1724

To fix this, tie the base reference of ep_data to the lifetime of the inode
rather than manually dropping it in destroy_ep_files(). Add an .evict_inode
callback to gadget_fs_operations that drops the reference when the inode is
finally destroyed. Remove the premature put_ep() call from
destroy_ep_files(). Additionally, to prevent a double-free in the error
path of activate_ep_files(), clear inode->i_private in
gadgetfs_create_file() before calling iput() if simple_start_creating()
fails.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
Link: https://syzkaller.appspot.com/ai_job?id=ae49a838-5eb9-4227-93a3-56ad2313483a
Signed-off-by: Aleksandr Nogikh <nogikh@google.com>

---
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index d87a8ab51..a03062986 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -1579,8 +1579,6 @@ static void destroy_ep_files (struct dev_data *dev)
 		/* break link to dcache */
 		simple_remove_by_name(dev->sb->s_root, ep->name, NULL);
 
-		put_ep (ep);
-
 		spin_lock_irq (&dev->lock);
 	}
 	spin_unlock_irq (&dev->lock);
@@ -1996,6 +1994,7 @@ static int gadgetfs_create_file (struct super_block *sb, char const *name,
 
 	dentry = simple_start_creating(sb->s_root, name);
 	if (IS_ERR(dentry)) {
+		inode->i_private = NULL;
 		iput(inode);
 		return PTR_ERR(dentry);
 	}
@@ -2006,9 +2005,18 @@ static int gadgetfs_create_file (struct super_block *sb, char const *name,
 	return 0;
 }
 
+static void gadgetfs_evict_inode(struct inode *inode)
+{
+	truncate_inode_pages_final(&inode->i_data);
+	clear_inode(inode);
+	if (inode->i_private && inode->i_fop == &ep_io_operations)
+		put_ep(inode->i_private);
+}
+
 static const struct super_operations gadget_fs_operations = {
 	.statfs =	simple_statfs,
 	.drop_inode =	inode_just_drop,
+	.evict_inode =	gadgetfs_evict_inode,
 };
 
 static int


base-commit: f5098b6bae761e346ebcd9da7f95622c04733cff
-- 
See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at syzkaller@googlegroups.com.


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
  2026-08-17 15:45     ` Alan Stern
@ 2026-08-17 16:38       ` syzbot
  0 siblings, 0 replies; 13+ messages in thread
From: syzbot @ 2026-08-17 16:38 UTC (permalink / raw)
  To: asml.silence, axboe, brauner, gregkh, io-uring, jack, kartikey406,
	kees, linux-kernel, linux-usb, mjguzik, nogikh, stern, syzbot,
	syzbot, syzkaller-bugs, syzkaller-upstream-moderation, torvalds,
	viro

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com
Tested-by: syzbot+df9e891bf8ea586f846b@syzkaller.appspotmail.com

Tested on:

commit:         8d3ae592 Linux 7.2
git tree:       git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ v7.2
console output: https://syzkaller.appspot.com/x/log.txt?x=16a91a25580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=c44651ea7dd2f307
dashboard link: https://syzkaller.appspot.com/bug?extid=df9e891bf8ea586f846b
compiler:       gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
patch:          https://syzkaller.appspot.com/x/patch.diff?x=15790679580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-08-17 16:38 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-31  1:28 [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
2026-07-31  4:26 ` Forwarded: [PATCH] usb: gadgetfs: fix use-after-free in ep_open() syzbot
2026-07-31  4:44 ` syzbot
2026-07-31  8:09 ` syzbot
2026-07-31 11:40 ` Forwarded: [PATCH v2] " syzbot
2026-08-17 13:42 ` [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open syzbot
2026-08-17 15:04   ` Jens Axboe
2026-08-17 15:45     ` Alan Stern
2026-08-17 16:38       ` syzbot
     [not found] <20260731042637.9137-1-kartikey406@gmail.com>
2026-07-31  5:42 ` syzbot
     [not found] <20260731044451.10817-1-kartikey406@gmail.com>
2026-07-31  6:59 ` syzbot
     [not found] <20260731080941.13394-1-kartikey406@gmail.com>
2026-07-31  9:08 ` syzbot
     [not found] <20260731114022.18295-1-kartikey406@gmail.com>
2026-07-31 16:21 ` syzbot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox