bluetooth pull request for net:

Core:
 
  - hci_sysfs: Fix NULL pointer dereference in device_del()
  - hci_sync: Fix not setting CE length properly
  - btqcomsmd: destroy RPMsg endpoints before freeing hci_dev
 
 Drivers:
 
  - btmtk: Declare MT7920 (MT7961 1a) Bluetooth firmware
  - btusb: mediatek: Fix leaked runtime PM reference in reset
  - btusb: Fix leaked runtime PM reference in btusb_reset
  - btusb: Fix UAF of btusb_data by rx_work
  - btusb: Properly disable remote wakeup for MT7922/MT7925 on Ryzen platform
  - btintel_pcie: validate packet_len before skb_put_data
  - btintel_pcie: fix tx_handle bounds off-by-one
  - btrtl: Don't leak return code when parsing firmware format v2
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCgA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmqge+cZHGx1aXoudm9u
 LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKdY3EACTdTdiS8WX8MHynuHzdp/n
 QsB6nHnt9MFfFqNSngmP2GzHB3dS9fGBHu19by4fSM/5DPpjBNT9h2UB9jMKZ3Ps
 lg2sLYTBm/9y0HYVYKfsZKhTYWU790OlNfCHNzYze0qYgHG6JB3KY87Rfay/GAsK
 4t2PCnRJNSq3O3QHsGmg8USo2Vz7xH0ucKBoblHHHWH90n9ZgTPATq0Pt9/9MwPa
 WxOcKbsgsGZ4ZeDbi+Tu5I9froR1bwh18q+c+f+0DXV75k8csJUy2Ro2G9GXXbW2
 96K7BpVy9BWKNnoSxWMy+jFZZRd0WmWHy8IcunYV6c65LLRlDjyJJ9fjCCbhT+ej
 Rsu7Ows0iTaBs/eWBaMyDLU12eNh2Fr5uFKkZXzMCcTLkPJWYkvOdtRA502D3F4t
 /dnk6dME5btAvHS/47QSlQ3JmpHuM1VL5GynLhkeIw2td16gDh3l5VbtUsANNbMn
 w9jL+YGgGA7nMClfR8VwKueypHqIClLQohbz14uvlqaXbsM5vgP86IF6jmSLdX2q
 DUSXeuk+EhuD5keP5bDriMRJCEKNYNO4DKlcCAkMc6nZqGJRin9tix1r9q9fQf2t
 0IQOXaHE9WRyqK3wbxVuOI8UaYRGB+DtoSWTJ4T0Rf8wo3oduMbGGRv3R9lnPjKA
 1NNB9rCRO5PmHLHkGOihRA==
 =hxd3
 -----END PGP SIGNATURE-----

Merge tag 'for-net-2026-09-08' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth

Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

Core:

 - hci_sysfs: Fix NULL pointer dereference in device_del()
 - hci_sync: Fix not setting CE length properly
 - btqcomsmd: destroy RPMsg endpoints before freeing hci_dev

Drivers:

 - btmtk: Declare MT7920 (MT7961 1a) Bluetooth firmware
 - btusb: mediatek: Fix leaked runtime PM reference in reset
 - btusb: Fix leaked runtime PM reference in btusb_reset
 - btusb: Fix UAF of btusb_data by rx_work
 - btusb: Properly disable remote wakeup for MT7922/MT7925 on Ryzen platform
 - btintel_pcie: validate packet_len before skb_put_data
 - btintel_pcie: fix tx_handle bounds off-by-one
 - btrtl: Don't leak return code when parsing firmware format v2

* tag 'for-net-2026-09-08' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: btusb: Fix leaked runtime PM reference in btusb_reset
  Bluetooth: btusb: mediatek: Fix leaked runtime PM reference in reset
  Bluetooth: btqcomsmd: destroy RPMsg endpoints before freeing hci_dev
  Bluetooth: hci_sysfs: Fix NULL pointer dereference in device_del()
  Bluetooth: btmtk: Declare MT7920 (MT7961 1a) Bluetooth firmware
  Bluetooth: hci_sync: Fix not setting CE length properly
  Bluetooth: btintel_pcie: fix tx_handle bounds off-by-one
  Bluetooth: btintel_pcie: validate packet_len before skb_put_data
  Bluetooth: btrtl: Don't leak return code when parsing firmware format v2
  Bluetooth: btusb: Fix UAF of btusb_data by rx_work
  Bluetooth: Properly disable remote wakeup for MT7922/MT7925 on Ryzen platform
====================

Link: https://patch.msgid.link/20260908212127.1022197-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-09-09 12:51:52 -07:00
commit bbee0759d3
8 changed files with 159 additions and 30 deletions

View File

@ -1099,7 +1099,7 @@ static void btintel_pcie_msix_tx_handle(struct btintel_pcie_data *data)
urbd0 = &txq->urbd0s[cr_tia];
if (urbd0->tfd_index > txq->count)
if (urbd0->tfd_index >= txq->count)
return;
cr_tia = (cr_tia + 1) % txq->count;
@ -1599,7 +1599,9 @@ static int btintel_pcie_submit_rx_work(struct btintel_pcie_data *data, u8 status
rfh_hdr = buf;
len = rfh_hdr->packet_len;
if (len <= 0) {
if (len == 0 || len > BTINTEL_PCIE_BUFFER_SIZE - sizeof(*rfh_hdr)) {
bt_dev_err(data->hdev, "Invalid packet_len %d (max %zu)", len,
BTINTEL_PCIE_BUFFER_SIZE - sizeof(*rfh_hdr));
ret = -EINVAL;
goto resubmit;
}

View File

@ -1374,16 +1374,6 @@ int btmtk_usb_setup(struct hci_dev *hdev)
break;
case 0x7922:
case 0x7925:
/*
* A remote wakeup could cause the device completely unresponsive, and
* recovering from such a state needs a power cycle.
*
* Since the remote wakeup capability is super broken, just disable it
* to get rid of the troubles. The device can still be autosuspended
* when the bluetooth interface is closed.
*/
device_set_wakeup_capable(&btmtk_data->udev->dev, false);
fallthrough;
case 0x7961:
case 0x7902:
case 0x6639:
@ -1587,5 +1577,6 @@ MODULE_FIRMWARE(FIRMWARE_MT7663);
MODULE_FIRMWARE(FIRMWARE_MT7668);
MODULE_FIRMWARE(FIRMWARE_MT7922);
MODULE_FIRMWARE(FIRMWARE_MT7961);
MODULE_FIRMWARE(FIRMWARE_MT7920);
MODULE_FIRMWARE(FIRMWARE_MT7925);
MODULE_FIRMWARE(FIRMWARE_MT7927);

View File

@ -7,6 +7,7 @@
#define FIRMWARE_MT7922 "mediatek/BT_RAM_CODE_MT7922_1_1_hdr.bin"
#define FIRMWARE_MT7902 "mediatek/BT_RAM_CODE_MT7902_1_1_hdr.bin"
#define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
#define FIRMWARE_MT7920 "mediatek/BT_RAM_CODE_MT7961_1a_2_hdr.bin"
#define FIRMWARE_MT7925 "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin"
#define FIRMWARE_MT7927 "mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin"

View File

@ -188,7 +188,10 @@ static int btqcomsmd_probe(struct platform_device *pdev)
return 0;
hci_free_dev:
rpmsg_destroy_ept(btq->cmd_channel);
rpmsg_destroy_ept(btq->acl_channel);
hci_free_dev(hdev);
return ret;
destroy_cmd_channel:
rpmsg_destroy_ept(btq->cmd_channel);
destroy_acl_channel:
@ -202,10 +205,11 @@ static void btqcomsmd_remove(struct platform_device *pdev)
struct btqcomsmd *btq = platform_get_drvdata(pdev);
hci_unregister_dev(btq->hdev);
hci_free_dev(btq->hdev);
rpmsg_destroy_ept(btq->cmd_channel);
rpmsg_destroy_ept(btq->acl_channel);
hci_free_dev(btq->hdev);
}
static const struct of_device_id btqcomsmd_of_match[] = {

View File

@ -591,7 +591,7 @@ static int rtlbt_parse_firmware_v2(struct hci_dev *hdev,
* headers.
*/
if (!key_id)
break;
continue;
rc = btrtl_parse_section(hdev, btrtl_dev, opcode,
ptr, section_len);
break;
@ -600,8 +600,7 @@ static int rtlbt_parse_firmware_v2(struct hci_dev *hdev,
ptr, section_len);
break;
default:
rc = 0;
break;
continue;
}
if (rc < 0) {
rtl_dev_err(hdev, "RTL: Parse section (%u) err %d",

View File

@ -6,6 +6,7 @@
* Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
*/
#include <linux/cpufeature.h>
#include <linux/dmi.h>
#include <linux/module.h>
#include <linux/usb.h>
@ -980,6 +981,8 @@ struct btqca_data {
#define BTUSB_USE_ALT3_FOR_WBS 15
#define BTUSB_ALT6_CONTINUOUS_TX 16
#define BTUSB_HW_SSR_ACTIVE 17
#define BTUSB_WAKEUP_BROKEN 18
#define BTUSB_RESET 19
struct btusb_data {
struct hci_dev *hdev;
@ -1054,13 +1057,15 @@ static void btusb_reset(struct hci_dev *hdev)
int err;
data = hci_get_drvdata(hdev);
/* This is not an unbalanced PM reference since the device will reset */
err = usb_autopm_get_interface(data->intf);
if (err) {
bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err);
return;
}
if (test_and_set_bit(BTUSB_RESET, &data->flags))
usb_autopm_put_interface_no_suspend(data->intf);
bt_dev_err(hdev, "Resetting usb device.");
usb_queue_reset_device(data->intf);
}
@ -2092,18 +2097,24 @@ static int btusb_close(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
cancel_delayed_work(&data->rx_work);
cancel_work_sync(&data->work);
cancel_work_sync(&data->waker);
skb_queue_purge(&data->acl_q);
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
clear_bit(BTUSB_DIAG_RUNNING, &data->flags);
btusb_stop_traffic(data);
/* rx_work must only be canceled once the URBs that can rearm it are
* gone, and it must be canceled synchronously since btusb_disconnect()
* frees the btusb_data it dereferences right after hci_unregister_dev().
*/
cancel_delayed_work_sync(&data->rx_work);
skb_queue_purge(&data->acl_q);
btusb_free_frags(data);
err = usb_autopm_get_interface(data->intf);
@ -2129,7 +2140,7 @@ static int btusb_flush(struct hci_dev *hdev)
BT_DBG("%s", hdev->name);
cancel_delayed_work(&data->rx_work);
cancel_delayed_work_sync(&data->rx_work);
skb_queue_purge(&data->acl_q);
@ -2923,8 +2934,11 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
}
err = usb_autopm_get_interface(data->intf);
if (err < 0)
if (err < 0) {
bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err);
clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
return err;
}
/* Release MediaTek ISO data interface */
btusb_mtk_release_iso_intf(hdev);
@ -2946,6 +2960,11 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id);
if (test_and_set_bit(BTUSB_RESET, &data->flags)) {
bt_dev_err(hdev, "last usb reset failed? Resetting again");
usb_autopm_put_interface_no_suspend(data->intf);
}
usb_queue_reset_device(data->intf);
clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
@ -2969,10 +2988,25 @@ static int btusb_send_frame_mtk(struct hci_dev *hdev, struct sk_buff *skb)
}
}
static inline bool platform_is_ryzen(void)
{
#ifdef CONFIG_X86
return boot_cpu_has(X86_FEATURE_ZEN);
#else
return false;
#endif
}
static inline bool is_direct_child_of_root_hub(struct usb_device *udev)
{
return udev->parent == udev->bus->root_hub;
}
static int btusb_mtk_setup(struct hci_dev *hdev)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
int err;
/* MediaTek WMT vendor cmd requiring below USB resources to
* complete the handshake.
@ -2989,7 +3023,40 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
btusb_mtk_claim_iso_intf(data);
}
return btmtk_usb_setup(hdev);
err = btmtk_usb_setup(hdev);
if (err)
return err;
switch (btmtk_data->dev_id) {
case 0x7922:
case 0x7925:
/*
* All reports seen to be relevant to Ryzen-based laptops. These
* NICs are usually used as OEM components thanks to some sort
* of reference designs.
*
* Their popularity on other platforms is unclear. While there
* is still a chance that the quirk may exist on other
* platforms, be cautious and only apply the quirk to direct
* children of Ryzen platforms's root hubs for the time being.
*
* In most cases the root hub is on the SoC or PCH, which needs
* the quirk. Unfortunately, this can't distinguish root hubs on
* PCIe add-in cards. Such roughness should be acceptable, as
* PCIe USB controller add-in cards are less commonly used
* nowadays. On the other hand, applying the quirk doesn't hurt
* any functionalities either, as the device can still be used
* as a wakeup source if desired.
*
* Theoretically, we could retrieve the root hub's PCI vendor ID
* with some hierarchy magic, but that's too intrusive...
*/
if (platform_is_ryzen() && is_direct_child_of_root_hub(data->udev))
set_bit(BTUSB_WAKEUP_BROKEN, &data->flags);
break;
}
return 0;
}
static int btusb_mtk_shutdown(struct hci_dev *hdev)
@ -4540,6 +4607,9 @@ static void btusb_disconnect(struct usb_interface *intf)
if (data->reset_gpio)
gpiod_put(data->reset_gpio);
if (test_and_clear_bit(BTUSB_RESET, &data->flags))
usb_autopm_put_interface_no_suspend(data->intf);
if (intf == data->intf) {
if (data->isoc)
usb_driver_release_interface(&btusb_driver, data->isoc);
@ -4565,11 +4635,26 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
BT_DBG("intf %p", intf);
/* Don't auto-suspend if there are connections or discovery in
* progress; external suspend calls shall never fail.
/*
* It is reported that remote wakeup events could sometimes cause some
* adapters completely unresponsive. Resetting the xHCI root hub doesn't
* help at all, and recovering from such a state needs a power cycle.
* Since disabling remote wakeup simply causes the USB core to gate
* runtime autosuspend as well due to needs_remote_wakeup == 1, let's do
* this ourselves to make our life easier. The interface can be safely
* autosuspended as long as remote wakeup is disabled, i.e., after
* closing the HCI device.
*
* Don't auto-suspend if there are connections or discovery in progress.
*
* External suspend calls shall never fail. Specifically, a device with
* broken remote wakeup may still take the advantage of remote wakeup in
* order to wake up the system from sleep if userspace has enabled it as
* a wakeup source.
*/
if (PMSG_IS_AUTO(message) &&
(hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
((test_bit(BTUSB_WAKEUP_BROKEN, &data->flags) && data->intf->needs_remote_wakeup) ||
hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
return -EBUSY;
if (data->suspend_count++)

View File

@ -4797,6 +4797,24 @@ static int hci_le_set_def_rate_sync(struct hci_dev *hdev)
cp.cont_num = cpu_to_le16(0x0001);
cp.supv_timeout = cpu_to_le16(0x000c); /* 120 ms */
/* The connection event length recommended in requests by a Peripheral
* uses units of 125 us with a valid range of 0x0001 to 0x7CFF
* (0.125 ms to 3.999875 s), so 0x0000 cannot be used. Also note that
* the Controller is not required to use these values:
*
* BLUETOOTH CORE SPECIFICATION Version 6.2 | Vol 4, Part E
* 7.8.158. LE Set Default Rate Parameters command
*
* The Min_CE_Length and Max_CE_Length parameters provide the
* Controller with the expected minimum and maximum length of the
* connection events. The Controller is not required to use these
* values.
*
* So it is safe to just use the minimum.
*/
cp.min_ce_len = cpu_to_le16(0x0001);
cp.max_ce_len = cpu_to_le16(0x0001);
return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_DEF_RATE,
sizeof(cp), &cp, HCI_CMD_TIMEOUT);
}
@ -7467,8 +7485,24 @@ static int hci_le_conn_rate_request_sync(struct hci_dev *hdev, void *data)
cp.max_latency = cpu_to_le16(params->max_latency);
cp.cont_num = cpu_to_le16(params->cont_num);
cp.supv_timeout = cpu_to_le16(params->rate_supv_timeout);
cp.min_ce_len = cpu_to_le16(0x0000);
cp.max_ce_len = cpu_to_le16(0x0000);
/* The connection event length recommended in requests by a Peripheral
* uses units of 125 us with a valid range of 0x0001 to 0x7CFF
* (0.125 ms to 3.999875 s), so 0x0000 cannot be used. Also note that
* the Controller is not required to use these values:
*
* BLUETOOTH CORE SPECIFICATION Version 6.2 | Vol 4, Part E
* 7.8.157. LE Connection Rate Request command
*
* The Min_CE_Length and Max_CE_Length parameters provide the
* Controller with the expected minimum and maximum length of the
* connection events. The Controller is not required to use these
* values.
*
* So it is safe to just use the minimum.
*/
cp.min_ce_len = cpu_to_le16(0x0001);
cp.max_ce_len = cpu_to_le16(0x0001);
hci_dev_unlock(hdev);

View File

@ -13,7 +13,10 @@ static const struct class bt_class = {
static void bt_link_release(struct device *dev)
{
struct hci_conn *conn = to_hci_conn(dev);
struct device *parent = dev->parent;
kfree(conn);
put_device(parent);
}
static const struct device_type bt_link = {
@ -21,6 +24,16 @@ static const struct device_type bt_link = {
.release = bt_link_release,
};
/*
* The rfcomm tty device will possibly retain even when conn
* is down, and sysfs doesn't support move zombie device,
* so we should move the device before conn device is destroyed.
*/
static int __match_tty(struct device *dev, const void *data)
{
return !strncmp(dev_name(dev), "rfcomm", 6);
}
void hci_conn_init_sysfs(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
@ -29,7 +42,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn)
conn->dev.type = &bt_link;
conn->dev.class = &bt_class;
conn->dev.parent = &hdev->dev;
conn->dev.parent = get_device(&hdev->dev);
device_initialize(&conn->dev);
}
@ -69,7 +82,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
while (1) {
struct device *dev;
dev = device_find_any_child(&conn->dev);
dev = device_find_child(&conn->dev, NULL, __match_tty);
if (!dev)
break;
device_move(dev, NULL, DPM_ORDER_DEV_LAST);