summaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorBalakrishna Godavarthi <bgodavar@codeaurora.org>2018-08-22 14:04:12 +0200
committerMarcel Holtmann <marcel@holtmann.org>2018-09-27 11:59:58 +0200
commit5a637751e216de2cad77f24f92b9e97e61e459d9 (patch)
tree785040a68ed7202d218b21efee4c282e3c82b404 /drivers/bluetooth
parentBluetooth: hci_serdev: clear HCI_UART_PROTO_READY to avoid closing proto races (diff)
downloadlinux-5a637751e216de2cad77f24f92b9e97e61e459d9.tar.xz
linux-5a637751e216de2cad77f24f92b9e97e61e459d9.zip
Bluetooth: hci_serdev: Add protocol check in hci_uart_dequeue().
This will help to check the status of protocol while dequeuing an skb packet. In some instaces we will end up kernel crash, where proto close is called and we trying to dequeue an packet. [ 500.142902] [<ffffff80080f9ce4>] do_raw_spin_lock+0x1c/0xe0 [ 500.148643] [<ffffff80088f1c7c>] _raw_spin_lock_irqsave+0x38/0x48 [ 500.154917] [<ffffff8008780ce8>] skb_dequeue+0x28/0x84 [ 500.160209] [<ffffff8000ad6f48>] 0xffffff8000ad6f48 [ 500.165230] [<ffffff8000ad6610>] 0xffffff8000ad6610 [ 500.170257] [<ffffff80080c7ce8>] process_one_work+0x238/0x3e4 [ 500.176174] [<ffffff80080c8330>] worker_thread+0x2bc/0x3d4 [ 500.181821] [<ffffff80080cdabc>] kthread+0x138/0x140 [ 500.186945] [<ffffff80080844e0>] ret_from_fork+0x10/0x18 Signed-off-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/hci_serdev.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c
index 46e20444ba19..a541e6ee085e 100644
--- a/drivers/bluetooth/hci_serdev.c
+++ b/drivers/bluetooth/hci_serdev.c
@@ -57,9 +57,10 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
{
struct sk_buff *skb = hu->tx_skb;
- if (!skb)
- skb = hu->proto->dequeue(hu);
- else
+ if (!skb) {
+ if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
+ skb = hu->proto->dequeue(hu);
+ } else
hu->tx_skb = NULL;
return skb;