* [PATCH v2] usb: gadget: inode: fix use-after-free of struct ep_data
@ 2026-09-05 14:49 Adriano Cordova
0 siblings, 0 replies; only message in thread
From: Adriano Cordova @ 2026-09-05 14:49 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: linux-usb, Alan Stern, Adriano Cordova,
syzbot+7bf725ed337e37307001
gadgetfs_unbind() -> destroy_ep_files() frees each struct ep_data via
put_ep(), but the inode still points at that ep_data through ->i_private
with no reference of its own. A concurrent openat() on an endpoint file
can therefore reach ep_open() and dereference the freed ep_data (the
mutex fast path), even while the inode outlives it.
Give the inode its own reference: take get_ep() when the endpoint inode
is created and drop it again from a new gadgetfs_evict_inode(), so an
ep_data can never be freed while any inode still points at it. This is
also safe against dcache pruning, since the inode reference keeps the
count >= 1 until the endpoint is removed from dev->epfiles.
The inode now holds ep_data for its whole lifetime, so an open() racing
with an unbind never dereferences freed ep_data.
Reported-by: syzbot+7bf725ed337e37307001@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=7bf725ed337e37307001
Tested-by: syzbot+7bf725ed337e37307001@syzkaller.appspotmail.com
Signed-off-by: Adriano Cordova <adrianox@gmail.com>
---
Changes in v2:
- v1: https://lore.kernel.org/all/20260904163827.216389-1-adrianox@gmail.com/
- Added further explanation in commit message.
drivers/usb/gadget/legacy/inode.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index db961aaa3740..089fa7119922 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -1626,6 +1626,8 @@ static int activate_ep_files (struct dev_data *dev)
if (!data->req)
goto enomem1;
+ /* The inode keeps this ep_data alive via ->i_private. */
+ get_ep(data);
err = gadgetfs_create_file (dev->sb, data->name,
data, &ep_io_operations);
if (err)
@@ -2015,9 +2017,20 @@ static int gadgetfs_create_file (struct super_block *sb, char const *name,
return 0;
}
+static void gadgetfs_evict_inode(struct inode *inode)
+{
+ /* EP inodes hold the reference on their ep_data via ->i_private. */
+ if (inode->i_fop == &ep_io_operations)
+ put_ep(inode->i_private);
+
+ truncate_inode_pages_final(&inode->i_data);
+ clear_inode(inode);
+}
+
static const struct super_operations gadget_fs_operations = {
.statfs = simple_statfs,
.drop_inode = inode_just_drop,
+ .evict_inode = gadgetfs_evict_inode,
};
static int
--
2.51.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-05 14:49 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-05 14:49 [PATCH v2] usb: gadget: inode: fix use-after-free of struct ep_data Adriano Cordova
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.