summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArkadiusz Bokowy <arkadiusz.bokowy@gmail.com>2023-09-20 18:30:07 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-10-25 12:54:18 +0300
commitc6878fa1730b8d9d59068b61593c63c7031f70e9 (patch)
tree5ef6e03291ebd89cd555427672781f30d26f6eba
parent40a33a129d99639921ce00d274cca44ba282f1ac (diff)
downloadlinux-c6878fa1730b8d9d59068b61593c63c7031f70e9.tar.xz
Bluetooth: vhci: Fix race when opening vhci device
commit 92d4abd66f7080075793970fc8f241239e58a9e7 upstream. When the vhci device is opened in the two-step way, i.e.: open device then write a vendor packet with requested controller type, the device shall respond with a vendor packet which includes HCI index of created interface. When the virtual HCI is created, the host sends a reset request to the controller. This request is processed by the vhci_send_frame() function. However, this request is send by a different thread, so it might happen that this HCI request will be received before the vendor response is queued in the read queue. This results in the HCI vendor response and HCI reset request inversion in the read queue which leads to improper behavior of btvirt: > dmesg [1754256.640122] Bluetooth: MGMT ver 1.22 [1754263.023806] Bluetooth: MGMT ver 1.22 [1754265.043775] Bluetooth: hci1: Opcode 0x c03 failed: -110 In order to synchronize vhci two-step open/setup process with virtual HCI initialization, this patch adds internal lock when queuing data in the vhci_send_frame() function. Signed-off-by: Arkadiusz Bokowy <arkadiusz.bokowy@gmail.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/bluetooth/hci_vhci.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 8469f9876dd2..31d70bad83d2 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -67,7 +67,10 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
struct vhci_data *data = hci_get_drvdata(hdev);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
+
+ mutex_lock(&data->open_mutex);
skb_queue_tail(&data->readq, skb);
+ mutex_unlock(&data->open_mutex);
wake_up_interruptible(&data->read_wait);
return 0;