All of lore.kernel.org
 help / color / mirror / Atom feed
From: Adriano Cordova <adrianox@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org, Alan Stern <stern@rowland.harvard.edu>,
	Adriano Cordova <adrianox@gmail.com>,
	syzbot+7bf725ed337e37307001@syzkaller.appspotmail.com
Subject: [PATCH v2] usb: gadget: inode: fix use-after-free of struct ep_data
Date: Sat,  5 Sep 2026 10:49:05 -0400	[thread overview]
Message-ID: <20260905144905.263941-1-adrianox@gmail.com> (raw)

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


                 reply	other threads:[~2026-09-05 14:49 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20260905144905.263941-1-adrianox@gmail.com \
    --to=adrianox@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=stern@rowland.harvard.edu \
    --cc=syzbot+7bf725ed337e37307001@syzkaller.appspotmail.com \
    /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 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.