Re: [PATCH] Bluetooth: btusb: fix use-after-free in force_poll_sync

From: Luiz Augusto von Dentz

Date: Wed Nov 04 2026 - 15:26:16 EST


Hi YuanZhe,

On Mon, Nov 2, 2026 at 6:04 AM YuanZhe Liu
<25031212351@xxxxxxxxxxxxxxxxx> wrote:
>
> The force_poll_sync debugfs file uses the driver's struct btusb_data as
> its private data. The file is created under hdev->debugfs and is removed
> only when the HCI device is released, while btusb_disconnect() frees
> btusb_data unconditionally. The HCI device can outlive the driver data,
> for example when an HCI socket still references it, so reading or
> writing the already opened file then dereferences freed memory:
>
> BUG: KASAN: slab-use-after-free in force_poll_sync_read+0x129/0x140
> Read of size 1 at addr ffff88800cfb7038
> ...
> Freed by task ...:
> kfree
> btusb_disconnect
>
> Remove the debugfs file before the private data is freed.
> debugfs_remove() waits for callers that are already inside the file
> operations, and any later access fails with -EIO instead of reaching the
> driver, so btusb_data can no longer be dereferenced after it is gone.
>
> Fixes: 800fe5ec302e ("Bluetooth: btusb: Add support for queuing during polling interval")
> Cc: stable@xxxxxxxxxxxxxxx
> Co-developed-by: Bin Yu <byu@xxxxxxxxxxxxx>
> Signed-off-by: Bin Yu <byu@xxxxxxxxxxxxx>
> Co-developed-by: Cheng Wen <wencheng@xxxxxxxxxxxxx>
> Signed-off-by: Cheng Wen <wencheng@xxxxxxxxxxxxx>
> Signed-off-by: YuanZhe Liu <25031212351@xxxxxxxxxxxxxxxxx>
> ---
> drivers/bluetooth/btusb.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index dc7191bf4234..d928580512fa 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -1066,6 +1066,8 @@ struct btusb_data {
> int (*disconnect)(struct hci_dev *hdev);
>
> int oob_wake_irq; /* irq for out-of-band wake-on-bt */
> +
> + struct dentry *force_poll_sync_dentry;
> };
>
> static void btusb_reset(struct hci_dev *hdev)
> @@ -4560,8 +4562,9 @@ static int btusb_probe(struct usb_interface *intf,
>
> usb_set_intfdata(intf, data);
>
> - debugfs_create_file("force_poll_sync", 0644, hdev->debugfs, data,
> - &force_poll_sync_fops);
> + data->force_poll_sync_dentry =
> + debugfs_create_file("force_poll_sync", 0644, hdev->debugfs,
> + data, &force_poll_sync_fops);
>
> return 0;
>
> @@ -4602,6 +4605,9 @@ static void btusb_disconnect(struct usb_interface *intf)
> if (!data)
> return;
>
> + debugfs_remove(data->force_poll_sync_dentry);
> + data->force_poll_sync_dentry = NULL;
> +
> hdev = data->hdev;
> usb_set_intfdata(data->intf, NULL);
>
> --
> 2.34.1

Looks like nedev sashiko has found a problem with these changes:

https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261102113654.8724-1-25031212351%40stu.xidian.edu.cn

--
Luiz Augusto von Dentz