• Uttkarsh Aggarwal's avatar
    usb: gadget: f_fs: Add unbind event before functionfs_unbind · efb6b535
    Uttkarsh Aggarwal authored
    While exercising the unbind path, with the current implementation
    the functionfs_unbind would be calling which waits for the ffs->mutex
    to be available, however within the same time ffs_ep0_read is invoked
    & if no setup packets are pending, it will invoke function
    wait_event_interruptible_exclusive_locked_irq which by definition waits
    for the ev.count to be increased inside the same mutex for which
    functionfs_unbind is waiting.
    This creates deadlock situation because the functionfs_unbind won't
    get the lock until ev.count is increased which can only happen if
    the caller ffs_func_unbind can proceed further.
    
    Following is the illustration:
    
    	CPU1				CPU2
    
    ffs_func_unbind()		ffs_ep0_read()
    				mutex_lock(ffs->mutex)
    				wait_event(ffs->ev.count)
    functionfs_unbind()
      mutex_lock(ffs->mutex)
      mutex_unlock(ffs->mutex)
    
    ffs_event_add()
    
    <deadlock>
    
    Fix this by moving the event unbind before functionfs_unbind
    to ensure the ev.count is incrased properly.
    
    Fixes: 6a19da11 ("usb: gadget: f_fs: Prevent race during ffs_ep0_queue_wait")
    Cc: stable <stable@kernel.org>
    Signed-off-by: default avatarUttkarsh Aggarwal <quic_uaggarwa@quicinc.com>
    Link: https://lore.kernel.org/r/20230525092854.7992-1-quic_uaggarwa@quicinc.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    efb6b535
f_fs.c 90.3 KB