Re: [syzbot] KASAN: use-after-free Write in gadgetfs_kill_sb

From: Alan Stern
Date: Tue Dec 13 2022 - 20:00:23 EST


On Tue, Dec 13, 2022 at 12:51:26PM -0800, syzbot wrote:
> Hello,
>
> syzbot has tested the proposed patch but the reproducer is still triggering an issue:
> INFO: rcu detected stall in corrupted
>
> rcu: INFO: rcu_preempt detected expedited stalls on CPUs/tasks: { P4116 } 2668 jiffies s: 2777 root: 0x0/T
> rcu: blocking rcu_node structures (internal RCU debug):
>
>
> Tested on:
>
> commit: 830b3c68 Linux 6.1
> git tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
> console output: https://syzkaller.appspot.com/x/log.txt?x=12066e8b880000
> kernel config: https://syzkaller.appspot.com/x/.config?x=5a194ed4fc682723
> dashboard link: https://syzkaller.appspot.com/bug?extid=33d7ad66d65044b93f16
> compiler: Debian clang version 13.0.1-++20220126092033+75e33f71c2da-1~exp1~20220126212112.63, GNU ld (GNU Binutils for Debian) 2.35.2
> patch: https://syzkaller.appspot.com/x/patch.diff?x=16793e8f880000

Let's see if this is related to the patch or something completely
independent.

Alan Stern

#syz test: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ 830b3c68c1fb

drivers/usb/gadget/legacy/inode.c | 39 +++++++++++++++++++++++++++++++-------
1 file changed, 32 insertions(+), 7 deletions(-)

Index: usb-devel/drivers/usb/gadget/legacy/inode.c
===================================================================
--- usb-devel.orig/drivers/usb/gadget/legacy/inode.c
+++ usb-devel/drivers/usb/gadget/legacy/inode.c
@@ -229,6 +229,7 @@ static void put_ep (struct ep_data *data
*/

static const char *CHIP;
+static DEFINE_MUTEX(sb_mutex); /* Serialize superblock maintenance */

/*----------------------------------------------------------------------*/

@@ -2010,13 +2011,23 @@ gadgetfs_fill_super (struct super_block
{
struct inode *inode;
struct dev_data *dev;
+ int rc;

- if (the_device)
- return -ESRCH;
+ printk(KERN_INFO "fill_super A\n");
+ mutex_lock(&sb_mutex);
+
+ if (the_device) {
+ rc = -ESRCH;
+ goto Done;
+ }
+ printk(KERN_INFO "fill_super B\n");

CHIP = usb_get_gadget_udc_name();
- if (!CHIP)
- return -ENODEV;
+ if (!CHIP) {
+ rc = -ENODEV;
+ goto Done;
+ }
+ printk(KERN_INFO "fill_super C\n");

/* superblock */
sb->s_blocksize = PAGE_SIZE;
@@ -2029,6 +2040,7 @@ gadgetfs_fill_super (struct super_block
inode = gadgetfs_make_inode (sb,
NULL, &simple_dir_operations,
S_IFDIR | S_IRUGO | S_IXUGO);
+ printk(KERN_INFO "fill_super D\n");
if (!inode)
goto Enomem;
inode->i_op = &simple_dir_inode_operations;
@@ -2039,11 +2051,13 @@ gadgetfs_fill_super (struct super_block
* user mode code can use it for sanity checks, like we do.
*/
dev = dev_new ();
+ printk(KERN_INFO "fill_super E\n");
if (!dev)
goto Enomem;

dev->sb = sb;
dev->dentry = gadgetfs_create_file(sb, CHIP, dev, &ep0_operations);
+ printk(KERN_INFO "fill_super F\n");
if (!dev->dentry) {
put_dev(dev);
goto Enomem;
@@ -2053,13 +2067,18 @@ gadgetfs_fill_super (struct super_block
* from binding to a controller.
*/
the_device = dev;
- return 0;
+ rc = 0;
+ goto Done;

-Enomem:
+ Enomem:
kfree(CHIP);
CHIP = NULL;
+ rc = -ENOMEM;

- return -ENOMEM;
+ Done:
+ printk(KERN_INFO "fill_super G\n");
+ mutex_unlock(&sb_mutex);
+ return rc;
}

/* "mount -t gadgetfs path /dev/gadget" ends up here */
@@ -2081,13 +2100,19 @@ static int gadgetfs_init_fs_context(stru
static void
gadgetfs_kill_sb (struct super_block *sb)
{
+ printk(KERN_INFO "kill_sb A\n");
+ mutex_lock(&sb_mutex);
+ printk(KERN_INFO "kill_sb B\n");
kill_litter_super (sb);
+ printk(KERN_INFO "kill_sb C\n");
if (the_device) {
put_dev (the_device);
the_device = NULL;
}
kfree(CHIP);
CHIP = NULL;
+ printk(KERN_INFO "kill_sb D\n");
+ mutex_unlock(&sb_mutex);
}

/*----------------------------------------------------------------------*/