diff options
| author | ZhaoJinming <zhaojinming@uniontech.com> | 2026-08-11 16:47:37 +0800 |
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2026-09-15 15:43:51 -0400 |
| commit | 8ec80e64922fc4f8217d2b6df42ba74434ef4a40 (patch) | |
| tree | d6cc5d86b07291e469f60821f98f363a4f2df6e0 | |
| parent | c447dc14354599a80a49d11785660f8acc367a9f (diff) | |
| download | linux-next-8ec80e64922fc4f8217d2b6df42ba74434ef4a40.tar.gz linux-next-8ec80e64922fc4f8217d2b6df42ba74434ef4a40.zip | |
Bluetooth: virtio_bt: Fix use-after-free and memory leak in probe error paths
When virtbt_open_vdev() fails in virtbt_probe(), hci_free_dev(hdev) is
called without first calling hci_unregister_dev(hdev). Since
hci_register_dev() already succeeded, the HCI device remains registered
while its memory is freed, leading to a use-after-free when accessed
via sysfs or HCI sockets.
Additionally, the probe function leaks the virtio_bluetooth structure
(vbt) in several error paths:
- When virtio_find_vqs() fails, vbt is not freed.
- When hci_alloc_dev() or hci_register_dev() fails, vbt is not freed.
- When virtbt_open_vdev() fails, vbt is not freed.
Furthermore, when virtbt_open_vdev() fails after virtio_device_ready()
has been called, the device is left live (DRIVER_OK set) while its
virtqueues are torn down, and any scheduled work is not flushed,
potentially allowing a use-after-free from device-initiated callbacks.
Fix all of these by restructuring the error labels to properly unwind
in reverse order of the allocation/registration sequence. The new
labels err_del_vqs and err_free_vbt ensure that del_vqs and kfree(vbt)
are called as appropriate for each failure point. For the
virtbt_open_vdev() failure path, call virtio_reset_device() and
virtbt_close_vdev() before unregistering the HCI device, matching the
cleanup pattern in virtbt_remove().
Signed-off-by: ZhaoJinming <zhaojinming@uniontech.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
| -rw-r--r-- | drivers/bluetooth/virtio_bt.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c index c20d54088c8c..8c55b538deef 100644 --- a/drivers/bluetooth/virtio_bt.c +++ b/drivers/bluetooth/virtio_bt.c @@ -315,12 +315,12 @@ static int virtbt_probe(struct virtio_device *vdev) err = virtio_find_vqs(vdev, VIRTBT_NUM_VQS, vbt->vqs, vqs_info, NULL); if (err) - return err; + goto err_free_vbt; hdev = hci_alloc_dev(); if (!hdev) { err = -ENOMEM; - goto failed; + goto err_del_vqs; } vbt->hdev = hdev; @@ -390,20 +390,25 @@ static int virtbt_probe(struct virtio_device *vdev) if (hci_register_dev(hdev) < 0) { hci_free_dev(hdev); err = -EBUSY; - goto failed; + goto err_del_vqs; } virtio_device_ready(vdev); err = virtbt_open_vdev(vbt); - if (err) - goto open_failed; + if (err) { + hci_unregister_dev(hdev); + virtio_reset_device(vdev); + virtbt_close_vdev(vbt); + hci_free_dev(hdev); + goto err_del_vqs; + } return 0; -open_failed: - hci_free_dev(hdev); -failed: +err_del_vqs: vdev->config->del_vqs(vdev); +err_free_vbt: + kfree(vbt); return err; } |
