Skip to content

Commit a9ee77a

Browse files
Sebastian Andrzej Siewiorholtmann
Sebastian Andrzej Siewior
authored andcommitted
Bluetooth: avoid recursive locking in hci_send_to_channel()
Mart reported a deadlock in -RT in the call path: hci_send_monitor_ctrl_event() -> hci_send_to_channel() because both functions acquire the same read lock hci_sk_list.lock. This is also a mainline issue because the qrwlock implementation is writer fair (the traditional rwlock implementation is reader biased). To avoid the deadlock there is now __hci_send_to_channel() which expects the readlock to be held. Fixes: 38ceaa0 ("Bluetooth: Add support for sending MGMT commands and events to monitor") Reported-by: Mart van de Wege <mvdwege@gmail.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
1 parent 1f01d8b commit a9ee77a

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

net/bluetooth/hci_sock.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,15 +251,13 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
251251
}
252252

253253
/* Send frame to sockets with specific channel */
254-
void hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
255-
int flag, struct sock *skip_sk)
254+
static void __hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
255+
int flag, struct sock *skip_sk)
256256
{
257257
struct sock *sk;
258258

259259
BT_DBG("channel %u len %d", channel, skb->len);
260260

261-
read_lock(&hci_sk_list.lock);
262-
263261
sk_for_each(sk, &hci_sk_list.head) {
264262
struct sk_buff *nskb;
265263

@@ -285,6 +283,13 @@ void hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
285283
kfree_skb(nskb);
286284
}
287285

286+
}
287+
288+
void hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
289+
int flag, struct sock *skip_sk)
290+
{
291+
read_lock(&hci_sk_list.lock);
292+
__hci_send_to_channel(channel, skb, flag, skip_sk);
288293
read_unlock(&hci_sk_list.lock);
289294
}
290295

@@ -388,8 +393,8 @@ void hci_send_monitor_ctrl_event(struct hci_dev *hdev, u16 event,
388393
hdr->index = index;
389394
hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
390395

391-
hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
392-
HCI_SOCK_TRUSTED, NULL);
396+
__hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
397+
HCI_SOCK_TRUSTED, NULL);
393398
kfree_skb(skb);
394399
}
395400

0 commit comments

Comments
 (0)