Revert "Bluetooth: hci_core: Fix use-after-free in vhci_flush()"

This reverts commit bc0819a25e which is
commit 1d6123102e9fbedc8d25bf4731da6d513173e49e upstream.

It breaks the Android kernel abi and can be brought back in the future
in an abi-safe way if it is really needed.

Bug: 161946584
Change-Id: Id182067e3ab35d3c51f9a114af331cea5589e0ac
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2025-07-13 13:44:57 +00:00
parent 50ec333673
commit 170440ba3c
2 changed files with 4 additions and 32 deletions

View File

@@ -29,7 +29,6 @@
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/rculist.h> #include <linux/rculist.h>
#include <linux/srcu.h>
#include <linux/android_kabi.h> #include <linux/android_kabi.h>
#include <net/bluetooth/hci.h> #include <net/bluetooth/hci.h>
@@ -350,7 +349,6 @@ struct amp_assoc {
struct hci_dev { struct hci_dev {
struct list_head list; struct list_head list;
struct srcu_struct srcu;
struct mutex lock; struct mutex lock;
struct ida unset_handle_ida; struct ida unset_handle_ida;

View File

@@ -65,7 +65,7 @@ static DEFINE_IDA(hci_index_ida);
/* Get HCI device by index. /* Get HCI device by index.
* Device is held on return. */ * Device is held on return. */
static struct hci_dev *__hci_dev_get(int index, int *srcu_index) struct hci_dev *hci_dev_get(int index)
{ {
struct hci_dev *hdev = NULL, *d; struct hci_dev *hdev = NULL, *d;
@@ -78,8 +78,6 @@ static struct hci_dev *__hci_dev_get(int index, int *srcu_index)
list_for_each_entry(d, &hci_dev_list, list) { list_for_each_entry(d, &hci_dev_list, list) {
if (d->id == index) { if (d->id == index) {
hdev = hci_dev_hold(d); hdev = hci_dev_hold(d);
if (srcu_index)
*srcu_index = srcu_read_lock(&d->srcu);
break; break;
} }
} }
@@ -87,22 +85,6 @@ static struct hci_dev *__hci_dev_get(int index, int *srcu_index)
return hdev; return hdev;
} }
struct hci_dev *hci_dev_get(int index)
{
return __hci_dev_get(index, NULL);
}
static struct hci_dev *hci_dev_get_srcu(int index, int *srcu_index)
{
return __hci_dev_get(index, srcu_index);
}
static void hci_dev_put_srcu(struct hci_dev *hdev, int srcu_index)
{
srcu_read_unlock(&hdev->srcu, srcu_index);
hci_dev_put(hdev);
}
/* ---- Inquiry support ---- */ /* ---- Inquiry support ---- */
bool hci_discovery_active(struct hci_dev *hdev) bool hci_discovery_active(struct hci_dev *hdev)
@@ -608,9 +590,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev)
int hci_dev_reset(__u16 dev) int hci_dev_reset(__u16 dev)
{ {
struct hci_dev *hdev; struct hci_dev *hdev;
int err, srcu_index; int err;
hdev = hci_dev_get_srcu(dev, &srcu_index); hdev = hci_dev_get(dev);
if (!hdev) if (!hdev)
return -ENODEV; return -ENODEV;
@@ -632,7 +614,7 @@ int hci_dev_reset(__u16 dev)
err = hci_dev_do_reset(hdev); err = hci_dev_do_reset(hdev);
done: done:
hci_dev_put_srcu(hdev, srcu_index); hci_dev_put(hdev);
return err; return err;
} }
@@ -2442,11 +2424,6 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
if (!hdev) if (!hdev)
return NULL; return NULL;
if (init_srcu_struct(&hdev->srcu)) {
kfree(hdev);
return NULL;
}
hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
hdev->esco_type = (ESCO_HV1); hdev->esco_type = (ESCO_HV1);
hdev->link_mode = (HCI_LM_ACCEPT); hdev->link_mode = (HCI_LM_ACCEPT);
@@ -2692,9 +2669,6 @@ void hci_unregister_dev(struct hci_dev *hdev)
list_del(&hdev->list); list_del(&hdev->list);
write_unlock(&hci_dev_list_lock); write_unlock(&hci_dev_list_lock);
synchronize_srcu(&hdev->srcu);
cleanup_srcu_struct(&hdev->srcu);
cancel_work_sync(&hdev->rx_work); cancel_work_sync(&hdev->rx_work);
cancel_work_sync(&hdev->cmd_work); cancel_work_sync(&hdev->cmd_work);
cancel_work_sync(&hdev->tx_work); cancel_work_sync(&hdev->tx_work);