• Dmitry Torokhov's avatar
    Input: uinput - avoid crash when sending FF request to device going away · 6b4877c7
    Dmitry Torokhov authored
    If FF request comes in while uinput device is going away,
    uinput_request_send() will fail with -ENODEV, and uinput_request_submit()
    will attempt to mark the slot as unused by calling uinput_request_done().
    Unfortunately in this case we haven't initialized request->done completion
    yet, and we get a crash:
    
    [   39.402036] BUG: spinlock bad magic on CPU#1, fftest/3108
    [   39.402046]  lock: 0xffff88006a93bb00, .magic: 00000000, .owner: /39, .owner_cpu: 1217155072
    [   39.402055] CPU: 1 PID: 3108 Comm: fftest Tainted: G        W 4.13.0+ #15
    [   39.402059] Hardware name: LENOVO 20HQS0EG02/20HQS0EG02, BIOS N1MET37W (1.22 ) 07/04/2017
    [   39.402064]  0000000000000086 f0fad82f3ceaa120 ffff88006a93b9a0 ffffffff9de941bb
    [   39.402077]  ffff88026df8ae00 ffff88006a93bb00 ffff88006a93b9c0 ffffffff9dca62b7
    [   39.402088]  ffff88006a93bb00 ffff88006a93baf8 ffff88006a93b9e0 ffffffff9dca62e7
    [   39.402099] Call Trace:
    [   39.402112]  [<ffffffff9de941bb>] dump_stack+0x4d/0x63
    [   39.402123]  [<ffffffff9dca62b7>] spin_dump+0x97/0x9c
    [   39.402130]  [<ffffffff9dca62e7>] spin_bug+0x2b/0x2d
    [   39.402138]  [<ffffffff9dca6373>] do_raw_spin_lock+0x28/0xfd
    [   39.402147]  [<ffffffff9e3055cd>] _raw_spin_lock_irqsave+0x19/0x1f
    [   39.402154]  [<ffffffff9dca05b7>] complete+0x1d/0x48
    [   39.402162]  [<ffffffffc04f30af>] 0xffffffffc04f30af
    [   39.402167]  [<ffffffffc04f468c>] 0xffffffffc04f468c
    [   39.402177]  [<ffffffff9dd59c16>] ? __slab_free+0x22f/0x359
    [   39.402184]  [<ffffffff9dcc13e9>] ? tk_clock_read+0xc/0xe
    [   39.402189]  [<ffffffffc04f471f>] 0xffffffffc04f471f
    [   39.402195]  [<ffffffff9dc9ffe5>] ? __wake_up+0x44/0x4b
    [   39.402200]  [<ffffffffc04f3240>] ? 0xffffffffc04f3240
    [   39.402207]  [<ffffffff9e0f57f3>] erase_effect+0xa1/0xd2
    [   39.402214]  [<ffffffff9e0f58c6>] input_ff_flush+0x43/0x5c
    [   39.402219]  [<ffffffffc04f32ad>] 0xffffffffc04f32ad
    [   39.402227]  [<ffffffff9e0f174f>] input_flush_device+0x3d/0x51
    [   39.402234]  [<ffffffff9e0f69ae>] evdev_flush+0x49/0x5c
    [   39.402243]  [<ffffffff9dd62d6e>] filp_close+0x3f/0x65
    [   39.402253]  [<ffffffff9dd7dcf7>] put_files_struct+0x66/0xc1
    [   39.402261]  [<ffffffff9dd7ddeb>] exit_files+0x47/0x4e
    [   39.402270]  [<ffffffff9dc6b329>] do_exit+0x483/0x969
    [   39.402278]  [<ffffffff9dc73211>] ? recalc_sigpending_tsk+0x3d/0x44
    [   39.402285]  [<ffffffff9dc6c7a2>] do_group_exit+0x42/0xb0
    [   39.402293]  [<ffffffff9dc767e1>] get_signal+0x58d/0x5bf
    [   39.402300]  [<ffffffff9dc03701>] do_signal+0x37/0x53e
    [   39.402307]  [<ffffffff9e0f8401>] ? evdev_ioctl_handler+0xac8/0xb04
    [   39.402314]  [<ffffffff9e0f8464>] ? evdev_ioctl+0x10/0x12
    [   39.402321]  [<ffffffff9dd74cfa>] ? do_vfs_ioctl+0x42e/0x501
    [   39.402328]  [<ffffffff9dc0170e>] prepare_exit_to_usermode+0x66/0x90
    [   39.402333]  [<ffffffff9dc0181b>] syscall_return_slowpath+0xe3/0xec
    [   39.402339]  [<ffffffff9e305b7b>] int_ret_from_sys_call+0x25/0x8f
    
    While we could solve this by simply initializing the completion earlier, we
    are better off rearranging the code a bit so we avoid calling complete() on
    requests that we did not send out. This patch consolidates marking request
    slots as free in one place (in uinput_request_submit(), the same place
    where we acquire them) and having everyone else simply signal completion
    of the requests.
    
    Fixes: 00ce756c ("Input: uinput - mark failed submission requests as free")
    Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
    6b4877c7
uinput.c 23.7 KB