mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
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>
This commit is contained in:
parent
ac043b566a
commit
9fb154391d
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user