Bluetooth: vhci: Fix race at creating hci device
hci_vhci driver creates a hci device object dynamically upon each HCI_VENDOR_PKT write. Although it checks the already created object and returns an error, it's still racy and may build multiple hci_dev objects concurrently when parallel writes are performed, as the device tracks only a single hci_dev object. This patch introduces a mutex to protect against the concurrent device creations. Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
60f5f5d3a1
commit
c7c999cb18
|
@ -50,6 +50,7 @@ struct vhci_data {
|
|||
wait_queue_head_t read_wait;
|
||||
struct sk_buff_head readq;
|
||||
|
||||
struct mutex open_mutex;
|
||||
struct delayed_work open_timeout;
|
||||
};
|
||||
|
||||
|
@ -87,12 +88,15 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vhci_create_device(struct vhci_data *data, __u8 opcode)
|
||||
static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
struct sk_buff *skb;
|
||||
__u8 dev_type;
|
||||
|
||||
if (data->hdev)
|
||||
return -EBADFD;
|
||||
|
||||
/* bits 0-1 are dev_type (BR/EDR or AMP) */
|
||||
dev_type = opcode & 0x03;
|
||||
|
||||
|
@ -151,6 +155,17 @@ static int vhci_create_device(struct vhci_data *data, __u8 opcode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vhci_create_device(struct vhci_data *data, __u8 opcode)
|
||||
{
|
||||
int err;
|
||||
|
||||
mutex_lock(&data->open_mutex);
|
||||
err = __vhci_create_device(data, opcode);
|
||||
mutex_unlock(&data->open_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline ssize_t vhci_get_user(struct vhci_data *data,
|
||||
struct iov_iter *from)
|
||||
{
|
||||
|
@ -191,11 +206,6 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
|
|||
case HCI_VENDOR_PKT:
|
||||
cancel_delayed_work_sync(&data->open_timeout);
|
||||
|
||||
if (data->hdev) {
|
||||
kfree_skb(skb);
|
||||
return -EBADFD;
|
||||
}
|
||||
|
||||
opcode = *((__u8 *) skb->data);
|
||||
skb_pull(skb, 1);
|
||||
|
||||
|
@ -320,6 +330,7 @@ static int vhci_open(struct inode *inode, struct file *file)
|
|||
skb_queue_head_init(&data->readq);
|
||||
init_waitqueue_head(&data->read_wait);
|
||||
|
||||
mutex_init(&data->open_mutex);
|
||||
INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);
|
||||
|
||||
file->private_data = data;
|
||||
|
|
Loading…
Reference in New Issue