Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Luiz Augusto von Dentz says:

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

- hci_sync: Fix hci_le_create_conn_sync
- MGMT: Fix list corruption and UAF in command complete handlers
- L2CAP: Disconnect if received packet's SDU exceeds IMTU
- L2CAP: Disconnect if sum of payload sizes exceed SDU
- L2CAP: Fix accepting multiple L2CAP_ECRED_CONN_REQ
- L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp()
- L2CAP: Validate L2CAP_INFO_RSP payload length before access
- L2CAP: Fix use-after-free in l2cap_unregister_user
- ISO: Fix defer tests being unstable
- HIDP: Fix possible UAF
- SMP: make SM/PER/KDU/BI-04-C happy
- qca: fix ROM version reading on WCN3998 chips

* tag 'for-net-2026-03-12' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
Bluetooth: qca: fix ROM version reading on WCN3998 chips
Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access
Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp()
Bluetooth: L2CAP: Fix accepting multiple L2CAP_ECRED_CONN_REQ
Bluetooth: L2CAP: Fix use-after-free in l2cap_unregister_user
Bluetooth: HIDP: Fix possible UAF
Bluetooth: MGMT: Fix list corruption and UAF in command complete handlers
Bluetooth: hci_sync: Fix hci_le_create_conn_sync
Bluetooth: ISO: Fix defer tests being unstable
Bluetooth: SMP: make SM/PER/KDU/BI-04-C happy
Bluetooth: LE L2CAP: Disconnect if sum of payload sizes exceed SDU
Bluetooth: LE L2CAP: Disconnect if received packet's SDU exceeds IMTU
====================

Link: https://patch.msgid.link/20260312200655.1215688-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+53 -31
+2
drivers/bluetooth/btqca.c
··· 787 787 */ 788 788 if (soc_type == QCA_WCN3988) 789 789 rom_ver = ((soc_ver & 0x00000f00) >> 0x05) | (soc_ver & 0x0000000f); 790 + else if (soc_type == QCA_WCN3998) 791 + rom_ver = ((soc_ver & 0x0000f000) >> 0x07) | (soc_ver & 0x0000000f); 790 792 else 791 793 rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f); 792 794
+2 -2
net/bluetooth/hci_conn.c
··· 1944 1944 return false; 1945 1945 1946 1946 done: 1947 + conn->iso_qos = *qos; 1948 + 1947 1949 if (hci_cmd_sync_queue(hdev, set_cig_params_sync, 1948 1950 UINT_PTR(qos->ucast.cig), NULL) < 0) 1949 1951 return false; ··· 2015 2013 } 2016 2014 2017 2015 hci_conn_hold(cis); 2018 - 2019 - cis->iso_qos = *qos; 2020 2016 cis->state = BT_BOUND; 2021 2017 2022 2018 return cis;
+1 -1
net/bluetooth/hci_sync.c
··· 6627 6627 * state. 6628 6628 */ 6629 6629 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { 6630 - hci_scan_disable_sync(hdev); 6631 6630 hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED); 6631 + hci_scan_disable_sync(hdev); 6632 6632 } 6633 6633 6634 6634 /* Update random address, but set require_privacy to false so
+14 -2
net/bluetooth/hidp/core.c
··· 986 986 skb_queue_purge(&session->intr_transmit); 987 987 fput(session->intr_sock->file); 988 988 fput(session->ctrl_sock->file); 989 - l2cap_conn_put(session->conn); 989 + if (session->conn) 990 + l2cap_conn_put(session->conn); 990 991 kfree(session); 991 992 } 992 993 ··· 1165 1164 1166 1165 down_write(&hidp_session_sem); 1167 1166 1167 + /* Drop L2CAP reference immediately to indicate that 1168 + * l2cap_unregister_user() shall not be called as it is already 1169 + * considered removed. 1170 + */ 1171 + if (session->conn) { 1172 + l2cap_conn_put(session->conn); 1173 + session->conn = NULL; 1174 + } 1175 + 1168 1176 hidp_session_terminate(session); 1169 1177 1170 1178 cancel_work_sync(&session->dev_init); ··· 1311 1301 * Instead, this call has the same semantics as if user-space tried to 1312 1302 * delete the session. 1313 1303 */ 1314 - l2cap_unregister_user(session->conn, &session->user); 1304 + if (session->conn) 1305 + l2cap_unregister_user(session->conn, &session->user); 1306 + 1315 1307 hidp_session_put(session); 1316 1308 1317 1309 module_put_and_kthread_exit(0);
+31 -20
net/bluetooth/l2cap_core.c
··· 1678 1678 1679 1679 int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) 1680 1680 { 1681 - struct hci_dev *hdev = conn->hcon->hdev; 1682 1681 int ret; 1683 1682 1684 1683 /* We need to check whether l2cap_conn is registered. If it is not, we 1685 - * must not register the l2cap_user. l2cap_conn_del() is unregisters 1686 - * l2cap_conn objects, but doesn't provide its own locking. Instead, it 1687 - * relies on the parent hci_conn object to be locked. This itself relies 1688 - * on the hci_dev object to be locked. So we must lock the hci device 1689 - * here, too. */ 1684 + * must not register the l2cap_user. l2cap_conn_del() unregisters 1685 + * l2cap_conn objects under conn->lock, and we use the same lock here 1686 + * to protect access to conn->users and conn->hchan. 1687 + */ 1690 1688 1691 - hci_dev_lock(hdev); 1689 + mutex_lock(&conn->lock); 1692 1690 1693 1691 if (!list_empty(&user->list)) { 1694 1692 ret = -EINVAL; ··· 1707 1709 ret = 0; 1708 1710 1709 1711 out_unlock: 1710 - hci_dev_unlock(hdev); 1712 + mutex_unlock(&conn->lock); 1711 1713 return ret; 1712 1714 } 1713 1715 EXPORT_SYMBOL(l2cap_register_user); 1714 1716 1715 1717 void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) 1716 1718 { 1717 - struct hci_dev *hdev = conn->hcon->hdev; 1718 - 1719 - hci_dev_lock(hdev); 1719 + mutex_lock(&conn->lock); 1720 1720 1721 1721 if (list_empty(&user->list)) 1722 1722 goto out_unlock; ··· 1723 1727 user->remove(conn, user); 1724 1728 1725 1729 out_unlock: 1726 - hci_dev_unlock(hdev); 1730 + mutex_unlock(&conn->lock); 1727 1731 } 1728 1732 EXPORT_SYMBOL(l2cap_unregister_user); 1729 1733 ··· 4612 4616 4613 4617 switch (type) { 4614 4618 case L2CAP_IT_FEAT_MASK: 4615 - conn->feat_mask = get_unaligned_le32(rsp->data); 4619 + if (cmd_len >= sizeof(*rsp) + sizeof(u32)) 4620 + conn->feat_mask = get_unaligned_le32(rsp->data); 4616 4621 4617 4622 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { 4618 4623 struct l2cap_info_req req; ··· 4632 4635 break; 4633 4636 4634 4637 case L2CAP_IT_FIXED_CHAN: 4635 - conn->remote_fixed_chan = rsp->data[0]; 4638 + if (cmd_len >= sizeof(*rsp) + sizeof(rsp->data[0])) 4639 + conn->remote_fixed_chan = rsp->data[0]; 4636 4640 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; 4637 4641 conn->info_ident = 0; 4638 4642 ··· 5057 5059 u16 mtu, mps; 5058 5060 __le16 psm; 5059 5061 u8 result, rsp_len = 0; 5060 - int i, num_scid; 5062 + int i, num_scid = 0; 5061 5063 bool defer = false; 5062 5064 5063 5065 if (!enable_ecred) ··· 5066 5068 memset(pdu, 0, sizeof(*pdu)); 5067 5069 5068 5070 if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) { 5071 + result = L2CAP_CR_LE_INVALID_PARAMS; 5072 + goto response; 5073 + } 5074 + 5075 + /* Check if there are no pending channels with the same ident */ 5076 + __l2cap_chan_list_id(conn, cmd->ident, l2cap_ecred_list_defer, 5077 + &num_scid); 5078 + if (num_scid) { 5069 5079 result = L2CAP_CR_LE_INVALID_PARAMS; 5070 5080 goto response; 5071 5081 } ··· 5430 5424 u8 *data) 5431 5425 { 5432 5426 struct l2cap_chan *chan, *tmp; 5433 - struct l2cap_ecred_conn_rsp *rsp = (void *) data; 5427 + struct l2cap_ecred_reconf_rsp *rsp = (void *)data; 5434 5428 u16 result; 5435 5429 5436 5430 if (cmd_len < sizeof(*rsp)) ··· 5438 5432 5439 5433 result = __le16_to_cpu(rsp->result); 5440 5434 5441 - BT_DBG("result 0x%4.4x", rsp->result); 5435 + BT_DBG("result 0x%4.4x", result); 5442 5436 5443 5437 if (!result) 5444 5438 return 0; ··· 6668 6662 return -ENOBUFS; 6669 6663 } 6670 6664 6671 - if (chan->imtu < skb->len) { 6672 - BT_ERR("Too big LE L2CAP PDU"); 6665 + if (skb->len > chan->imtu) { 6666 + BT_ERR("Too big LE L2CAP PDU: len %u > %u", skb->len, 6667 + chan->imtu); 6668 + l2cap_send_disconn_req(chan, ECONNRESET); 6673 6669 return -ENOBUFS; 6674 6670 } 6675 6671 ··· 6697 6689 sdu_len, skb->len, chan->imtu); 6698 6690 6699 6691 if (sdu_len > chan->imtu) { 6700 - BT_ERR("Too big LE L2CAP SDU length received"); 6692 + BT_ERR("Too big LE L2CAP SDU length: len %u > %u", 6693 + skb->len, sdu_len); 6694 + l2cap_send_disconn_req(chan, ECONNRESET); 6701 6695 err = -EMSGSIZE; 6702 6696 goto failed; 6703 6697 } ··· 6735 6725 6736 6726 if (chan->sdu->len + skb->len > chan->sdu_len) { 6737 6727 BT_ERR("Too much LE L2CAP data received"); 6728 + l2cap_send_disconn_req(chan, ECONNRESET); 6738 6729 err = -EINVAL; 6739 6730 goto failed; 6740 6731 }
+2 -5
net/bluetooth/mgmt.c
··· 2195 2195 sk = cmd->sk; 2196 2196 2197 2197 if (status) { 2198 - mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, 2199 - status); 2200 - mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true, 2201 - cmd_status_rsp, &status); 2198 + mgmt_cmd_status(cmd->sk, hdev->id, cmd->opcode, status); 2202 2199 goto done; 2203 2200 } 2204 2201 ··· 5374 5377 5375 5378 mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, 5376 5379 mgmt_status(status), &rp, sizeof(rp)); 5377 - mgmt_pending_remove(cmd); 5380 + mgmt_pending_free(cmd); 5378 5381 5379 5382 hci_dev_unlock(hdev); 5380 5383 bt_dev_dbg(hdev, "add monitor %d complete, status %d",
+1 -1
net/bluetooth/smp.c
··· 2743 2743 if (!test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags) && 2744 2744 !crypto_memneq(key, smp->local_pk, 64)) { 2745 2745 bt_dev_err(hdev, "Remote and local public keys are identical"); 2746 - return SMP_UNSPECIFIED; 2746 + return SMP_DHKEY_CHECK_FAILED; 2747 2747 } 2748 2748 2749 2749 memcpy(smp->remote_pk, key, 64);