aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-10-02 03:16:22 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-10-02 04:37:07 -0400
commit02e246aee868e982eecc25ee97d02acf2c2b8884 (patch)
tree9616f22ee9a75d0b0c85eb984da3154e3a17a3f7 /net/bluetooth
parent6a57dba9f0107b21cab06f7c898935d747d4738a (diff)
Bluetooth: Fix lockdep warning with l2cap_chan_connect
The L2CAP connection's channel list lock (conn->chan_lock) must never be taken while already holding a channel lock (chan->lock) in order to avoid lock-inversion and lockdep warnings. So far the l2cap_chan_connect function has acquired the chan->lock early in the function and then later called l2cap_chan_add(conn, chan) which will try to take the conn->chan_lock. This violates the correct order of taking the locks and may lead to the following type of lockdep warnings: -> #1 (&conn->chan_lock){+.+...}: [<c109324d>] lock_acquire+0x9d/0x140 [<c188459c>] mutex_lock_nested+0x6c/0x420 [<d0aab48e>] l2cap_chan_add+0x1e/0x40 [bluetooth] [<d0aac618>] l2cap_chan_connect+0x348/0x8f0 [bluetooth] [<d0cc9a91>] lowpan_control_write+0x221/0x2d0 [bluetooth_6lowpan] -> #0 (&chan->lock){+.+.+.}: [<c10928d8>] __lock_acquire+0x1a18/0x1d20 [<c109324d>] lock_acquire+0x9d/0x140 [<c188459c>] mutex_lock_nested+0x6c/0x420 [<d0ab05fd>] l2cap_connect_cfm+0x1dd/0x3f0 [bluetooth] [<d0a909c4>] hci_le_meta_evt+0x11a4/0x1260 [bluetooth] [<d0a910eb>] hci_event_packet+0x3ab/0x3120 [bluetooth] [<d0a7cb08>] hci_rx_work+0x208/0x4a0 [bluetooth] CPU0 CPU1 ---- ---- lock(&conn->chan_lock); lock(&chan->lock); lock(&conn->chan_lock); lock(&chan->lock); Before calling l2cap_chan_add() the channel is not part of the conn->chan_l list, and can therefore only be accessed by the L2CAP user (such as l2cap_sock.c). We can therefore assume that it is the responsibility of the user to handle mutual exclusion until this point (which we can see is already true in l2cap_sock.c by it in many places touching chan members without holding chan->lock). Since the hci_conn and by exctension l2cap_conn creation in the l2cap_chan_connect() function depend on chan details we cannot simply add a mutex_lock(&conn->chan_lock) in the beginning of the function (since the conn object doesn't yet exist there). What we can do however is move the chan->lock taking later into the function where we already have the conn object and can that way take conn->chan_lock first. This patch implements the above strategy and does some other necessary changes such as using __l2cap_chan_add() which assumes conn->chan_lock is held, as well as adding a second needed label so the unlocking happens as it should. Reported-by: Jukka Rissanen <jukka.rissanen@linux.intel.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Tested-by: Jukka Rissanen <jukka.rissanen@linux.intel.com> Acked-by: Jukka Rissanen <jukka.rissanen@linux.intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap_core.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 8d53fc57faba..b6f9777e057d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6980,8 +6980,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
6980 6980
6981 hci_dev_lock(hdev); 6981 hci_dev_lock(hdev);
6982 6982
6983 l2cap_chan_lock(chan);
6984
6985 if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && 6983 if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
6986 chan->chan_type != L2CAP_CHAN_RAW) { 6984 chan->chan_type != L2CAP_CHAN_RAW) {
6987 err = -EINVAL; 6985 err = -EINVAL;
@@ -7078,17 +7076,20 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
7078 goto done; 7076 goto done;
7079 } 7077 }
7080 7078
7079 mutex_lock(&conn->chan_lock);
7080 l2cap_chan_lock(chan);
7081
7081 if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { 7082 if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
7082 hci_conn_drop(hcon); 7083 hci_conn_drop(hcon);
7083 err = -EBUSY; 7084 err = -EBUSY;
7084 goto done; 7085 goto chan_unlock;
7085 } 7086 }
7086 7087
7087 /* Update source addr of the socket */ 7088 /* Update source addr of the socket */
7088 bacpy(&chan->src, &hcon->src); 7089 bacpy(&chan->src, &hcon->src);
7089 chan->src_type = bdaddr_type(hcon, hcon->src_type); 7090 chan->src_type = bdaddr_type(hcon, hcon->src_type);
7090 7091
7091 l2cap_chan_add(conn, chan); 7092 __l2cap_chan_add(conn, chan);
7092 7093
7093 /* l2cap_chan_add takes its own ref so we can drop this one */ 7094 /* l2cap_chan_add takes its own ref so we can drop this one */
7094 hci_conn_drop(hcon); 7095 hci_conn_drop(hcon);
@@ -7114,8 +7115,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
7114 7115
7115 err = 0; 7116 err = 0;
7116 7117
7117done: 7118chan_unlock:
7118 l2cap_chan_unlock(chan); 7119 l2cap_chan_unlock(chan);
7120 mutex_unlock(&conn->chan_lock);
7121done:
7119 hci_dev_unlock(hdev); 7122 hci_dev_unlock(hdev);
7120 hci_dev_put(hdev); 7123 hci_dev_put(hdev);
7121 return err; 7124 return err;