From: "syzbot" <syzbot@kernel.org>
To: syzkaller-bugs@googlegroups.com,
Aleksandr Nogikh <nogikh@google.com>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
<linux-usb@vger.kernel.org>,
"Linus Torvalds" <torvalds@ppc970.osdl.org>
Cc: brauner@kernel.org, jack@suse.cz, kees@kernel.org,
linux-kernel@vger.kernel.org, mjguzik@gmail.com,
syzbot@lists.linux.dev, viro@zeniv.linux.org.uk
Subject: [PATCH] usb: gadgetfs: fix use-after-free in ep_open()
Date: Fri, 31 Jul 2026 13:24:50 +0000 (UTC) [thread overview]
Message-ID: <ee41fbfd-f368-4a06-95d6-ae9b4267fd82@mail.kernel.org> (raw)
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.
next reply other threads:[~2026-07-31 13:24 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-31 13:24 syzbot [this message]
-- strict thread matches above, loose matches on Subject: below --
2026-07-31 9:13 Deepanshu Kartikey
2026-07-31 10:37 ` Greg KH
2026-07-31 11:12 ` Deepanshu Kartikey
2026-07-31 13:22 ` Alan Stern
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ee41fbfd-f368-4a06-95d6-ae9b4267fd82@mail.kernel.org \
--to=syzbot@kernel.org \
--cc=brauner@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=jack@suse.cz \
--cc=kees@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mjguzik@gmail.com \
--cc=nogikh@google.com \
--cc=syzbot@lists.linux.dev \
--cc=syzkaller-bugs@googlegroups.com \
--cc=torvalds@ppc970.osdl.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®