• Alan Stern's avatar
    USB: gadget: fix GPF in gadgetfs · 6097614a
    Alan Stern authored
    commit f50b878f upstream.
    
    A NULL-pointer dereference bug in gadgetfs was uncovered by syzkaller:
    
    > kasan: GPF could be caused by NULL-ptr deref or user memory access
    > general protection fault: 0000 [#1] SMP KASAN
    > Dumping ftrace buffer:
    >    (ftrace buffer empty)
    > Modules linked in:
    > CPU: 2 PID: 4820 Comm: syz-executor0 Not tainted 4.12.0-rc4+ #5
    > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
    > task: ffff880039542dc0 task.stack: ffff88003bdd0000
    > RIP: 0010:__list_del_entry_valid+0x7e/0x170 lib/list_debug.c:51
    > RSP: 0018:ffff88003bdd6e50 EFLAGS: 00010246
    > RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000010000
    > RDX: 0000000000000000 RSI: ffffffff86504948 RDI: ffffffff86504950
    > RBP: ffff88003bdd6e68 R08: ffff880039542dc0 R09: ffffffff8778ce00
    > R10: ffff88003bdd6e68 R11: dffffc0000000000 R12: 0000000000000000
    > R13: dffffc0000000000 R14: 1ffff100077badd2 R15: ffffffff864d2e40
    > FS:  0000000000000000(0000) GS:ffff88006dc00000(0000) knlGS:0000000000000000
    > CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    > CR2: 000000002014aff9 CR3: 0000000006022000 CR4: 00000000000006e0
    > Call Trace:
    >  __list_del_entry include/linux/list.h:116 [inline]
    >  list_del include/linux/list.h:124 [inline]
    >  usb_gadget_unregister_driver+0x166/0x4c0 drivers/usb/gadget/udc/core.c:1387
    >  dev_release+0x80/0x160 drivers/usb/gadget/legacy/inode.c:1187
    >  __fput+0x332/0x7f0 fs/file_table.c:209
    >  ____fput+0x15/0x20 fs/file_table.c:245
    >  task_work_run+0x19b/0x270 kernel/task_work.c:116
    >  exit_task_work include/linux/task_work.h:21 [inline]
    >  do_exit+0x18a3/0x2820 kernel/exit.c:878
    >  do_group_exit+0x149/0x420 kernel/exit.c:982
    >  get_signal+0x77f/0x1780 kernel/signal.c:2318
    >  do_signal+0xd2/0x2130 arch/x86/kernel/signal.c:808
    >  exit_to_usermode_loop+0x1a7/0x240 arch/x86/entry/common.c:157
    >  prepare_exit_to_usermode arch/x86/entry/common.c:194 [inline]
    >  syscall_return_slowpath+0x3ba/0x410 arch/x86/entry/common.c:263
    >  entry_SYSCALL_64_fastpath+0xbc/0xbe
    > RIP: 0033:0x4461f9
    > RSP: 002b:00007fdac2b1ecf8 EFLAGS: 00000246 ORIG_RAX: 00000000000000ca
    > RAX: fffffffffffffe00 RBX: 00000000007080c8 RCX: 00000000004461f9
    > RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000007080c8
    > RBP: 00000000007080a8 R08: 0000000000000000 R09: 0000000000000000
    > R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
    > R13: 0000000000000000 R14: 00007fdac2b1f9c0 R15: 00007fdac2b1f700
    > Code: 00 00 00 00 ad de 49 39 c4 74 6a 48 b8 00 02 00 00 00 00 ad de
    > 48 89 da 48 39 c3 74 74 48 c1 ea 03 48 b8 00 00 00 00 00 fc ff df <80>
    > 3c 02 00 0f 85 92 00 00 00 48 8b 13 48 39 f2 75 66 49 8d 7c
    > RIP: __list_del_entry_valid+0x7e/0x170 lib/list_debug.c:51 RSP: ffff88003bdd6e50
    > ---[ end trace 30e94b1eec4831c8 ]---
    > Kernel panic - not syncing: Fatal exception
    
    The bug was caused by dev_release() failing to turn off its
    gadget_registered flag after unregistering the gadget driver.  As a
    result, when a later user closed the device file before writing a
    valid set of descriptors, dev_release() thought the gadget had been
    registered and tried to unregister it, even though it had not been.
    This led to the NULL pointer dereference.
    
    The fix is simple: turn off the flag when the gadget is unregistered.
    Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
    Reported-and-tested-by: default avatarAndrey Konovalov <andreyknvl@google.com>
    Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    6097614a
inode.c 50.8 KB