Re: [PATCH RFC] usb: gadgetfs: fix use-after-free in ep_open()
Aleksandr Nogikh <[email protected]> Fri, 31 Jul 2026 15:21:31 +0200
| Newsgroups | dev.linux.lists.syzbot |
|---|---|
| Message-ID | <CANp29Y5woqC4_8Awxuv0FU1sbK97+LFhHyLUn2uHku3nJ93b5g@mail.gmail.com> |
#syz upstream On Fri, Jul 31, 2026 at 10:13=E2=80=AFAM 'syzbot' via syzkaller-upstream-moderation <[email protected]> wrote: > > 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 o= f > 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 accesse= s > 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 ino= de > rather than manually dropping it in destroy_ep_files(). Add an .evict_ino= de > 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: [email protected] > Closes: https://syzkaller.appspot.com/bug?extid=3Ddf9e891bf8ea586f846b > Link: https://syzkaller.appspot.com/ai_job?id=3Dae49a838-5eb9-4227-93a3-5= 6ad2313483a > To: "Greg Kroah-Hartman" <[email protected]> > To: <[email protected]> > To: "Linus Torvalds" <[email protected]> > Cc: "Christian Brauner" <[email protected]> > Cc: "Jan Kara" <[email protected]> > Cc: "Kees Cook" <[email protected]> > Cc: <[email protected]> > Cc: "Mateusz Guzik" <[email protected]> > Cc: "Al Viro" <[email protected]> > > --- > diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legac= y/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 =3D simple_start_creating(sb->s_root, name); > if (IS_ERR(dentry)) { > + inode->i_private =3D NULL; > iput(inode); > return PTR_ERR(dentry); > } > @@ -2006,9 +2005,18 @@ static int gadgetfs_create_file (struct super_bloc= k *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 =3D=3D &ep_io_operations) > + put_ep(inode->i_private); > +} > + > static const struct super_operations gadget_fs_operations =3D { > .statfs =3D simple_statfs, > .drop_inode =3D inode_just_drop, > + .evict_inode =3D gadgetfs_evict_inode, > }; > > static int > > > base-commit: f5098b6bae761e346ebcd9da7f95622c04733cff > -- > This is an AI-generated patch subject to moderation. > Reply with '#syz upstream' to Sign-off the patch as a human author > and send it to the upstream kernel mailing lists. > Reply with '#syz reject' to reject it ('#syz unreject' to undo). > > 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 [email protected]. > > -- > You received this message because you are subscribed to the Google Groups= "syzkaller-upstream-moderation" group. > To unsubscribe from this group and stop receiving emails from it, send an= email to [email protected]. > To view this discussion visit https://groups.google.com/d/msgid/syzkaller= -upstream-moderation/a6f4f066-bd64-4a53-b3e0-0d71b34bf773%40mail.kernel.org= .