• Arjan van de Ven's avatar
    bluetooth: fix locking bug in the rfcomm socket cleanup handling · 4c8411f8
    Arjan van de Ven authored
    in net/bluetooth/rfcomm/sock.c, rfcomm_sk_state_change() does the
    following operation:
    
            if (parent && sock_flag(sk, SOCK_ZAPPED)) {
                    /* We have to drop DLC lock here, otherwise
                     * rfcomm_sock_destruct() will dead lock. */
                    rfcomm_dlc_unlock(d);
                    rfcomm_sock_kill(sk);
                    rfcomm_dlc_lock(d);
            }
    }
    
    which is fine, since rfcomm_sock_kill() will call sk_free() which will call
    rfcomm_sock_destruct() which takes the rfcomm_dlc_lock()... so far so good.
    
    HOWEVER, this assumes that the rfcomm_sk_state_change() function always gets
    called with the rfcomm_dlc_lock() taken. This is the case for all but one
    case, and in that case where we don't have the lock, we do a double unlock
    followed by an attempt to take the lock, which due to underflow isn't
    going anywhere fast.
    
    This patch fixes this by moving the stragling case inside the lock, like
    the other usages of the same call are doing in this code.
    
    This was found with the help of the www.kerneloops.org project, where this
    deadlock was observed 51 times at this point in time:
    http://www.kerneloops.org/search.php?search=rfcomm_sock_destructSigned-off-by: default avatarArjan van de Ven <arjan@linux.intel.com>
    Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    4c8411f8
core.c 47 KB