usb/gadget: copy_to_user called with spinlock held

From: Andrey Konovalov
Date: Thu Sep 21 2017 - 12:43:38 EST


Hi!

I've got the following report while fuzzing the kernel with syzkaller.

On commit ebb2c2437d8008d46796902ff390653822af6cc4 (Sep 18).

Line numbers might be a little off, due to some local changes to
gadgetfs code but the issue is AFAIU with calling copy_to_user() with
spinlock held in ep0_read(). I see that there's a FIXME exactly about
that and I was wondering if there's any chance of getting this fixed?

Thanks!

BUG: sleeping function called from invalid context at lib/usercopy.c:24
in_atomic(): 1, irqs_disabled(): 1, pid: 5948, name: syz-executor0
2 locks held by syz-executor0/5948:
#0: (&f->f_pos_lock){+.+.}, at: [<ffffffff81892809>]
__fdget_pos+0x149/0x1c0 fs/file.c:767
#1: (&(&dev->lock)->rlock){..-.}, at: [<ffffffff837b42d0>]
spin_lock_irq include/linux/spinlock.h:341 [inline]
#1: (&(&dev->lock)->rlock){..-.}, at: [<ffffffff837b42d0>]
ep0_read+0x580/0x1230 drivers/usb/gadget/legacy/inode.c:972
irq event stamp: 1220
hardirqs last enabled at (1219): [<ffffffff856cec8c>]
__raw_spin_unlock_irq include/linux/spinlock_api_smp.h:168 [inline]
hardirqs last enabled at (1219): [<ffffffff856cec8c>]
_raw_spin_unlock_irq+0x2c/0x60 kernel/locking/spinlock.c:199
hardirqs last disabled at (1220): [<ffffffff856ce989>]
__raw_spin_lock_irq include/linux/spinlock_api_smp.h:126 [inline]
hardirqs last disabled at (1220): [<ffffffff856ce989>]
_raw_spin_lock_irq+0x19/0x50 kernel/locking/spinlock.c:167
softirqs last enabled at (1022): [<ffffffff856d81dd>]
__do_softirq+0x5fd/0xc2d kernel/softirq.c:310
softirqs last disabled at (1013): [<ffffffff811924f1>] invoke_softirq
kernel/softirq.c:364 [inline]
softirqs last disabled at (1013): [<ffffffff811924f1>]
irq_exit+0x171/0x1a0 kernel/softirq.c:405
Preemption disabled at:
[<ffffffff837b42d0>] spin_lock_irq include/linux/spinlock.h:341 [inline]
[<ffffffff837b42d0>] ep0_read+0x580/0x1230 drivers/usb/gadget/legacy/inode.c:972
CPU: 1 PID: 5948 Comm: syz-executor0 Not tainted
4.14.0-rc1-42259-g18ca1418efd9 #216
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:16 [inline]
dump_stack+0x292/0x395 lib/dump_stack.c:52
___might_sleep+0x65c/0x720 kernel/sched/core.c:6015
__might_sleep+0x9a/0x190 kernel/sched/core.c:5968
__might_fault+0x15d/0x290 mm/memory.c:4499
_copy_to_user+0x2c/0xc0 lib/usercopy.c:24
copy_to_user include/linux/uaccess.h:154 [inline]
ep0_read+0x739/0x1230 drivers/usb/gadget/legacy/inode.c:987
__vfs_read+0x69d/0x890 fs/read_write.c:410
vfs_read+0x129/0x360 fs/read_write.c:446
SYSC_read fs/read_write.c:572 [inline]
SyS_read+0x100/0x240 fs/read_write.c:565
entry_SYSCALL_64_fastpath+0x23/0xc2
RIP: 0033:0x40cfb1
RSP: 002b:00007ff9c6b38b20 EFLAGS: 00000293 ORIG_RAX: 0000000000000000
RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 000000000040cfb1
RDX: 000000000000003c RSI: 00007ff9c6b38b70 RDI: 0000000000000005
RBP: 0000000000000005 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000708000
R13: 0000000000000000 R14: 00007ff9c6b399c0 R15: 00007ff9c6b39700

=====================================================
WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected
4.14.0-rc1-42259-g18ca1418efd9 #216 Tainted: G W
-----------------------------------------------------
syz-executor0/5948 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire:
(&mm->mmap_sem){++++}, at: [<ffffffff816eb04d>]
__might_fault+0x18d/0x290 mm/memory.c:4501

and this task is already holding:
(&(&dev->lock)->rlock){..-.}, at: [<ffffffff837b42d0>] spin_lock_irq
include/linux/spinlock.h:341 [inline]
(&(&dev->lock)->rlock){..-.}, at: [<ffffffff837b42d0>]
ep0_read+0x580/0x1230 drivers/usb/gadget/legacy/inode.c:972
which would create a new lock dependency:
(&(&dev->lock)->rlock){..-.} -> (&mm->mmap_sem){++++}

but this new dependency connects a SOFTIRQ-irq-safe lock:
(&(&dev->lock)->rlock){..-.}

... which became SOFTIRQ-irq-safe at:
mark_irqflags kernel/locking/lockdep.c:3077 [inline]
__lock_acquire+0x1d93/0x4550 kernel/locking/lockdep.c:3455
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
__raw_spin_lock include/linux/spinlock_api_smp.h:142 [inline]
_raw_spin_lock+0x32/0x50 kernel/locking/spinlock.c:151
spin_lock include/linux/spinlock.h:316 [inline]
gadgetfs_setup+0x212/0x1ea0 drivers/usb/gadget/legacy/inode.c:1320
dummy_timer+0x13bf/0x3970 drivers/usb/gadget/udc/dummy_hcd.c:1870
call_timer_fn+0x2a2/0x940 kernel/time/timer.c:1281
expire_timers kernel/time/timer.c:1320 [inline]
__run_timers+0x87f/0xd40 kernel/time/timer.c:1620
run_timer_softirq+0x83/0x140 kernel/time/timer.c:1646
__do_softirq+0x305/0xc2d kernel/softirq.c:284
invoke_softirq kernel/softirq.c:364 [inline]
irq_exit+0x171/0x1a0 kernel/softirq.c:405
exiting_irq arch/x86/include/asm/apic.h:638 [inline]
smp_apic_timer_interrupt+0x2b9/0x8d0 arch/x86/kernel/apic/apic.c:1048
apic_timer_interrupt+0x9d/0xb0 arch/x86/entry/entry_64.S:577
native_safe_halt+0x6/0x10 arch/x86/include/asm/irqflags.h:53
arch_safe_halt arch/x86/include/asm/paravirt.h:93 [inline]
default_idle+0x127/0x690 arch/x86/kernel/process.c:341
arch_cpu_idle+0xf/0x20 arch/x86/kernel/process.c:332
default_idle_call+0x3b/0x60 kernel/sched/idle.c:98
cpuidle_idle_call kernel/sched/idle.c:156 [inline]
do_idle+0x35c/0x440 kernel/sched/idle.c:246
cpu_startup_entry+0x1d/0x20 kernel/sched/idle.c:351
start_secondary+0x3de/0x500 arch/x86/kernel/smpboot.c:277
verify_cpu+0x0/0xfb

to a SOFTIRQ-irq-unsafe lock:
(&mm->mmap_sem){++++}

... which became SOFTIRQ-irq-unsafe at:
...
mark_irqflags kernel/locking/lockdep.c:3095 [inline]
__lock_acquire+0x1024/0x4550 kernel/locking/lockdep.c:3455
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
down_write_killable+0x8a/0x150 kernel/locking/rwsem.c:67
__bprm_mm_init fs/exec.c:297 [inline]
bprm_mm_init fs/exec.c:414 [inline]
do_execveat_common.isra.31+0xc8f/0x2200 fs/exec.c:1767
do_execve+0x36/0x50 fs/exec.c:1842
run_init_process+0x37/0x40 init/main.c:943
try_to_run_init_process+0x1c/0x50 init/main.c:952
kernel_init+0xfd/0x180 init/main.c:1025
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

other info that might help us debug this:

Possible interrupt unsafe locking scenario:

CPU0 CPU1
---- ----
lock(&mm->mmap_sem);
local_irq_disable();
lock(&(&dev->lock)->rlock);
lock(&mm->mmap_sem);
<Interrupt>
lock(&(&dev->lock)->rlock);

*** DEADLOCK ***

2 locks held by syz-executor0/5948:
#0: (&f->f_pos_lock){+.+.}, at: [<ffffffff81892809>]
__fdget_pos+0x149/0x1c0 fs/file.c:767
#1: (&(&dev->lock)->rlock){..-.}, at: [<ffffffff837b42d0>]
spin_lock_irq include/linux/spinlock.h:341 [inline]
#1: (&(&dev->lock)->rlock){..-.}, at: [<ffffffff837b42d0>]
ep0_read+0x580/0x1230 drivers/usb/gadget/legacy/inode.c:972

the dependencies between SOFTIRQ-irq-safe lock and the holding lock:
-> (&(&dev->lock)->rlock){..-.} ops: 27637 {
IN-SOFTIRQ-W at:
mark_irqflags kernel/locking/lockdep.c:3077 [inline]
__lock_acquire+0x1d93/0x4550 kernel/locking/lockdep.c:3455
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
__raw_spin_lock
include/linux/spinlock_api_smp.h:142 [inline]
_raw_spin_lock+0x32/0x50 kernel/locking/spinlock.c:151
spin_lock include/linux/spinlock.h:316 [inline]
gadgetfs_setup+0x212/0x1ea0
drivers/usb/gadget/legacy/inode.c:1320
dummy_timer+0x13bf/0x3970
drivers/usb/gadget/udc/dummy_hcd.c:1870
call_timer_fn+0x2a2/0x940 kernel/time/timer.c:1281
expire_timers kernel/time/timer.c:1320 [inline]
__run_timers+0x87f/0xd40 kernel/time/timer.c:1620
run_timer_softirq+0x83/0x140 kernel/time/timer.c:1646
__do_softirq+0x305/0xc2d kernel/softirq.c:284
invoke_softirq kernel/softirq.c:364 [inline]
irq_exit+0x171/0x1a0 kernel/softirq.c:405
exiting_irq arch/x86/include/asm/apic.h:638 [inline]
smp_apic_timer_interrupt+0x2b9/0x8d0
arch/x86/kernel/apic/apic.c:1048
apic_timer_interrupt+0x9d/0xb0 arch/x86/entry/entry_64.S:577
native_safe_halt+0x6/0x10 arch/x86/include/asm/irqflags.h:53
arch_safe_halt arch/x86/include/asm/paravirt.h:93 [inline]
default_idle+0x127/0x690 arch/x86/kernel/process.c:341
arch_cpu_idle+0xf/0x20 arch/x86/kernel/process.c:332
default_idle_call+0x3b/0x60 kernel/sched/idle.c:98
cpuidle_idle_call kernel/sched/idle.c:156 [inline]
do_idle+0x35c/0x440 kernel/sched/idle.c:246
cpu_startup_entry+0x1d/0x20 kernel/sched/idle.c:351
start_secondary+0x3de/0x500 arch/x86/kernel/smpboot.c:277
verify_cpu+0x0/0xfb
INITIAL USE at:
__lock_acquire+0x7aa/0x4550 kernel/locking/lockdep.c:3459
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
__raw_spin_lock_irq
include/linux/spinlock_api_smp.h:128 [inline]
_raw_spin_lock_irq+0x3e/0x50 kernel/locking/spinlock.c:167
dev_open+0x48/0x140 drivers/media/usb/gspca/gspca.c:1286
do_dentry_open+0x74e/0xd60 fs/open.c:752
vfs_open+0x10c/0x230 fs/open.c:866
do_last fs/namei.c:3387 [inline]
path_openat+0xf22/0x34d0 fs/namei.c:3527
do_filp_open+0x2a1/0x460 fs/namei.c:3562
do_sys_open+0x543/0x720 fs/open.c:1059
SYSC_open fs/open.c:1077 [inline]
SyS_open+0x32/0x40 fs/open.c:1072
entry_SYSCALL_64_fastpath+0x23/0xc2
}
... key at: [<ffffffff88779940>] __key.35734+0x0/0x40
... acquired at:
check_irq_usage kernel/locking/lockdep.c:1694 [inline]
check_prev_add_irq kernel/locking/lockdep_states.h:8 [inline]
check_prev_add+0x319/0x1780 kernel/locking/lockdep.c:1898
check_prevs_add kernel/locking/lockdep.c:2020 [inline]
validate_chain kernel/locking/lockdep.c:2469 [inline]
__lock_acquire+0x3296/0x4550 kernel/locking/lockdep.c:3498
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
__might_fault+0x213/0x290 mm/memory.c:4502
_copy_to_user+0x2c/0xc0 lib/usercopy.c:24
copy_to_user include/linux/uaccess.h:154 [inline]
ep0_read+0x739/0x1230 drivers/usb/gadget/legacy/inode.c:987
__vfs_read+0x69d/0x890 fs/read_write.c:410
vfs_read+0x129/0x360 fs/read_write.c:446
SYSC_read fs/read_write.c:572 [inline]
SyS_read+0x100/0x240 fs/read_write.c:565
entry_SYSCALL_64_fastpath+0x23/0xc2


the dependencies between the lock to be acquired
and SOFTIRQ-irq-unsafe lock:
-> (&mm->mmap_sem){++++} ops: 1801476 {
HARDIRQ-ON-W at:
mark_irqflags kernel/locking/lockdep.c:3091 [inline]
__lock_acquire+0xfb7/0x4550 kernel/locking/lockdep.c:3455
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
down_write_killable+0x8a/0x150 kernel/locking/rwsem.c:67
__bprm_mm_init fs/exec.c:297 [inline]
bprm_mm_init fs/exec.c:414 [inline]
do_execveat_common.isra.31+0xc8f/0x2200 fs/exec.c:1767
do_execve+0x36/0x50 fs/exec.c:1842
run_init_process+0x37/0x40 init/main.c:943
try_to_run_init_process+0x1c/0x50 init/main.c:952
kernel_init+0xfd/0x180 init/main.c:1025
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
HARDIRQ-ON-R at:
mark_irqflags kernel/locking/lockdep.c:3083 [inline]
__lock_acquire+0x70d/0x4550 kernel/locking/lockdep.c:3455
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
__might_fault+0x213/0x290 mm/memory.c:4502
__clear_user+0x28/0x70 arch/x86/lib/usercopy_64.c:19
clear_user+0x7e/0xb0 arch/x86/lib/usercopy_64.c:53
padzero fs/binfmt_elf.c:129 [inline]
load_elf_binary+0x3940/0x4fa0 fs/binfmt_elf.c:1058
search_binary_handler+0x146/0x480 fs/exec.c:1634
exec_binprm fs/exec.c:1676 [inline]
do_execveat_common.isra.31+0x16d2/0x2200 fs/exec.c:1798
do_execve+0x36/0x50 fs/exec.c:1842
run_init_process+0x37/0x40 init/main.c:943
try_to_run_init_process+0x1c/0x50 init/main.c:952
kernel_init+0xfd/0x180 init/main.c:1025
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
SOFTIRQ-ON-W at:
mark_irqflags kernel/locking/lockdep.c:3095 [inline]
__lock_acquire+0x1024/0x4550 kernel/locking/lockdep.c:3455
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
down_write_killable+0x8a/0x150 kernel/locking/rwsem.c:67
__bprm_mm_init fs/exec.c:297 [inline]
bprm_mm_init fs/exec.c:414 [inline]
do_execveat_common.isra.31+0xc8f/0x2200 fs/exec.c:1767
do_execve+0x36/0x50 fs/exec.c:1842
run_init_process+0x37/0x40 init/main.c:943
try_to_run_init_process+0x1c/0x50 init/main.c:952
kernel_init+0xfd/0x180 init/main.c:1025
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
SOFTIRQ-ON-R at:
mark_irqflags kernel/locking/lockdep.c:3087 [inline]
__lock_acquire+0x776/0x4550 kernel/locking/lockdep.c:3455
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
__might_fault+0x213/0x290 mm/memory.c:4502
__clear_user+0x28/0x70 arch/x86/lib/usercopy_64.c:19
clear_user+0x7e/0xb0 arch/x86/lib/usercopy_64.c:53
padzero fs/binfmt_elf.c:129 [inline]
load_elf_binary+0x3940/0x4fa0 fs/binfmt_elf.c:1058
search_binary_handler+0x146/0x480 fs/exec.c:1634
exec_binprm fs/exec.c:1676 [inline]
do_execveat_common.isra.31+0x16d2/0x2200 fs/exec.c:1798
do_execve+0x36/0x50 fs/exec.c:1842
run_init_process+0x37/0x40 init/main.c:943
try_to_run_init_process+0x1c/0x50 init/main.c:952
kernel_init+0xfd/0x180 init/main.c:1025
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
INITIAL USE at:
__lock_acquire+0x7aa/0x4550 kernel/locking/lockdep.c:3459
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
down_write_killable+0x8a/0x150 kernel/locking/rwsem.c:67
__bprm_mm_init fs/exec.c:297 [inline]
bprm_mm_init fs/exec.c:414 [inline]
do_execveat_common.isra.31+0xc8f/0x2200 fs/exec.c:1767
do_execve+0x36/0x50 fs/exec.c:1842
run_init_process+0x37/0x40 init/main.c:943
try_to_run_init_process+0x1c/0x50 init/main.c:952
kernel_init+0xfd/0x180 init/main.c:1025
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
}
... key at: [<ffffffff87303540>] __key.64135+0x0/0x40
... acquired at:
check_irq_usage kernel/locking/lockdep.c:1694 [inline]
check_prev_add_irq kernel/locking/lockdep_states.h:8 [inline]
check_prev_add+0x319/0x1780 kernel/locking/lockdep.c:1898
check_prevs_add kernel/locking/lockdep.c:2020 [inline]
validate_chain kernel/locking/lockdep.c:2469 [inline]
__lock_acquire+0x3296/0x4550 kernel/locking/lockdep.c:3498
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
__might_fault+0x213/0x290 mm/memory.c:4502
_copy_to_user+0x2c/0xc0 lib/usercopy.c:24
copy_to_user include/linux/uaccess.h:154 [inline]
ep0_read+0x739/0x1230 drivers/usb/gadget/legacy/inode.c:987
__vfs_read+0x69d/0x890 fs/read_write.c:410
vfs_read+0x129/0x360 fs/read_write.c:446
SYSC_read fs/read_write.c:572 [inline]
SyS_read+0x100/0x240 fs/read_write.c:565
entry_SYSCALL_64_fastpath+0x23/0xc2


stack backtrace:
CPU: 1 PID: 5948 Comm: syz-executor0 Tainted: G W
4.14.0-rc1-42259-g18ca1418efd9 #216
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:16 [inline]
dump_stack+0x292/0x395 lib/dump_stack.c:52
print_bad_irq_dependency kernel/locking/lockdep.c:1606 [inline]
check_usage+0xc46/0xc90 kernel/locking/lockdep.c:1638
check_irq_usage kernel/locking/lockdep.c:1694 [inline]
check_prev_add_irq kernel/locking/lockdep_states.h:8 [inline]
check_prev_add+0x319/0x1780 kernel/locking/lockdep.c:1898
check_prevs_add kernel/locking/lockdep.c:2020 [inline]
validate_chain kernel/locking/lockdep.c:2469 [inline]
__lock_acquire+0x3296/0x4550 kernel/locking/lockdep.c:3498
lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
__might_fault+0x213/0x290 mm/memory.c:4502
_copy_to_user+0x2c/0xc0 lib/usercopy.c:24
copy_to_user include/linux/uaccess.h:154 [inline]
ep0_read+0x739/0x1230 drivers/usb/gadget/legacy/inode.c:987
__vfs_read+0x69d/0x890 fs/read_write.c:410
vfs_read+0x129/0x360 fs/read_write.c:446
SYSC_read fs/read_write.c:572 [inline]
SyS_read+0x100/0x240 fs/read_write.c:565
entry_SYSCALL_64_fastpath+0x23/0xc2
RIP: 0033:0x40cfb1
RSP: 002b:00007ff9c6b38b20 EFLAGS: 00000293 ORIG_RAX: 0000000000000000
RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 000000000040cfb1
RDX: 000000000000003c RSI: 00007ff9c6b38b70 RDI: 0000000000000005
RBP: 0000000000000005 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000708000
R13: 0000000000000000 R14: 00007ff9c6b399c0 R15: 00007ff9c6b39700