• Dave Young's avatar
    bluetooth: rfcomm_dev_state_change deadlock fix · 537d59af
    Dave Young authored
    There's logic in __rfcomm_dlc_close:
    	rfcomm_dlc_lock(d);
    	d->state = BT_CLOSED;
    	d->state_changed(d, err);
    	rfcomm_dlc_unlock(d);
    
    In rfcomm_dev_state_change, it's possible that rfcomm_dev_put try to
    take the dlc lock, then we will deadlock.
    
    Here fixed it by unlock dlc before rfcomm_dev_get in
    rfcomm_dev_state_change.
    
    why not unlock just before rfcomm_dev_put? it's because there's
    another problem.  rfcomm_dev_get/rfcomm_dev_del will take
    rfcomm_dev_lock, but in rfcomm_dev_add the lock order is :
    rfcomm_dev_lock --> dlc lock
    
    so I unlock dlc before the taken of rfcomm_dev_lock.
    
    Actually it's a regression caused by commit
    1905f6c7 ("bluetooth :
    __rfcomm_dlc_close lock fix"), the dlc state_change could be two
    callbacks : rfcomm_sk_state_change and rfcomm_dev_state_change. I
    missed the rfcomm_sk_state_change that time.
    
    Thanks Arjan van de Ven <arjan@linux.intel.com> for the effort in
    commit 4c8411f8 ("bluetooth: fix
    locking bug in the rfcomm socket cleanup handling") but he missed the
    rfcomm_dev_state_change lock issue.
    Signed-off-by: default avatarDave Young <hidave.darkstar@gmail.com>
    Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    537d59af
tty.c 26 KB