From: Ben Hutchings Date: Sat, 29 Sep 2012 17:53:28 +0200 Subject: Bluetooth: Fix l2cap_conn_del() locking This is covered by commit 3df91ea20e744344100b10ae69a17211fcf5b207 ('Bluetooth: Revert to mutexes from RCU list') upstream. l2cap_conn_del() can race with various other functions that walk the channel list; in particular l2cap_conn_start() which is called from l2cap_info_timeout(). l2cap_chan_del() itself takes the chan_lock for writing, so instead of locking here we must move all channels onto a temporary list. Signed-off-by: Ben Hutchings --- --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -968,6 +968,7 @@ static void l2cap_info_timeout(unsigned static void l2cap_conn_del(struct hci_conn *hcon, int err) { struct l2cap_conn *conn = hcon->l2cap_data; + struct list_head chan_l; struct l2cap_chan *chan, *l; struct sock *sk; @@ -978,8 +979,13 @@ static void l2cap_conn_del(struct hci_co kfree_skb(conn->rx_skb); + INIT_LIST_HEAD(&chan_l); + write_lock_bh(&conn->chan_lock); + list_splice_init(&conn->chan_l, &chan_l); + write_unlock_bh(&conn->chan_lock); + /* Kill channels */ - list_for_each_entry_safe(chan, l, &conn->chan_l, list) { + list_for_each_entry_safe(chan, l, &chan_l, list) { sk = chan->sk; bh_lock_sock(sk); l2cap_chan_del(chan, err);