Re: [syzbot] [usb?] KASAN: slab-use-after-free Read in ep_open
From: Alan Stern
Date: Mon Aug 17 2026 - 12:08:37 EST
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@xxxxxxxxx>
> > 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@xxxxxxxxxxxxxxxxxxxxxxxxx
> > 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@xxxxxxxxxx>
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@xxxxxxxxxxxxxxxxxxxxxxxxx
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@xxxxxxxxxx>
---
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@xxxxxxxxxxxxxxxx.