]> git.baikalelectronics.ru Git - kernel.git/commit
bluetooth: fix locking bug in the rfcomm socket cleanup handling
authorArjan van de Ven <arjan@linux.intel.com>
Thu, 29 May 2008 08:32:47 +0000 (01:32 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 29 May 2008 08:32:47 +0000 (01:32 -0700)
commit0a00a6170d95e5aa64c16f447f46c2396766c975
tree4a2d592d9b41fabbd184ddaa7d2839f87f0a5ac9
parent6a6b70275fa91f7678c69c124b3ced45f049fc4b
bluetooth: fix locking bug in the rfcomm socket cleanup handling

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_destruct

Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bluetooth/rfcomm/core.c