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-02-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth

Luiz Augusto von Dentz says:

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

- purge error queues in socket destructors
- hci_sync: Fix CIS host feature condition
- L2CAP: Fix invalid response to L2CAP_ECRED_RECONF_REQ
- L2CAP: Fix result of L2CAP_ECRED_CONN_RSP when MTU is too short
- L2CAP: Fix response to L2CAP_ECRED_CONN_REQ
- L2CAP: Fix not checking output MTU is acceptable on L2CAP_ECRED_CONN_REQ
- L2CAP: Fix missing key size check for L2CAP_LE_CONN_REQ
- hci_qca: Cleanup on all setup failures

* tag 'for-net-2026-02-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
Bluetooth: L2CAP: Fix missing key size check for L2CAP_LE_CONN_REQ
Bluetooth: L2CAP: Fix not checking output MTU is acceptable on L2CAP_ECRED_CONN_REQ
Bluetooth: Fix CIS host feature condition
Bluetooth: L2CAP: Fix response to L2CAP_ECRED_CONN_REQ
Bluetooth: hci_qca: Cleanup on all setup failures
Bluetooth: purge error queues in socket destructors
Bluetooth: L2CAP: Fix result of L2CAP_ECRED_CONN_RSP when MTU is too short
Bluetooth: L2CAP: Fix invalid response to L2CAP_ECRED_RECONF_REQ
====================

Link: https://patch.msgid.link/20260223211634.3800315-1-luiz.dentz@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+109 -47
+14 -10
drivers/bluetooth/hci_qca.c
··· 2046 2046 } 2047 2047 2048 2048 out: 2049 - if (ret && retries < MAX_INIT_RETRIES) { 2050 - bt_dev_warn(hdev, "Retry BT power ON:%d", retries); 2049 + if (ret) { 2051 2050 qca_power_shutdown(hu); 2052 - if (hu->serdev) { 2053 - serdev_device_close(hu->serdev); 2054 - ret = serdev_device_open(hu->serdev); 2055 - if (ret) { 2056 - bt_dev_err(hdev, "failed to open port"); 2057 - return ret; 2051 + 2052 + if (retries < MAX_INIT_RETRIES) { 2053 + bt_dev_warn(hdev, "Retry BT power ON:%d", retries); 2054 + if (hu->serdev) { 2055 + serdev_device_close(hu->serdev); 2056 + ret = serdev_device_open(hu->serdev); 2057 + if (ret) { 2058 + bt_dev_err(hdev, "failed to open port"); 2059 + return ret; 2060 + } 2058 2061 } 2062 + retries++; 2063 + goto retry; 2059 2064 } 2060 - retries++; 2061 - goto retry; 2065 + return ret; 2062 2066 } 2063 2067 2064 2068 /* Setup bdaddr */
+5 -3
include/net/bluetooth/l2cap.h
··· 284 284 #define L2CAP_CR_LE_BAD_KEY_SIZE 0x0007 285 285 #define L2CAP_CR_LE_ENCRYPTION 0x0008 286 286 #define L2CAP_CR_LE_INVALID_SCID 0x0009 287 - #define L2CAP_CR_LE_SCID_IN_USE 0X000A 288 - #define L2CAP_CR_LE_UNACCEPT_PARAMS 0X000B 289 - #define L2CAP_CR_LE_INVALID_PARAMS 0X000C 287 + #define L2CAP_CR_LE_SCID_IN_USE 0x000A 288 + #define L2CAP_CR_LE_UNACCEPT_PARAMS 0x000B 289 + #define L2CAP_CR_LE_INVALID_PARAMS 0x000C 290 290 291 291 /* connect/create channel status */ 292 292 #define L2CAP_CS_NO_INFO 0x0000 ··· 493 493 #define L2CAP_RECONF_SUCCESS 0x0000 494 494 #define L2CAP_RECONF_INVALID_MTU 0x0001 495 495 #define L2CAP_RECONF_INVALID_MPS 0x0002 496 + #define L2CAP_RECONF_INVALID_CID 0x0003 497 + #define L2CAP_RECONF_INVALID_PARAMS 0x0004 496 498 497 499 struct l2cap_ecred_reconf_rsp { 498 500 __le16 result;
+1
net/bluetooth/hci_sock.c
··· 2166 2166 mgmt_cleanup(sk); 2167 2167 skb_queue_purge(&sk->sk_receive_queue); 2168 2168 skb_queue_purge(&sk->sk_write_queue); 2169 + skb_queue_purge(&sk->sk_error_queue); 2169 2170 } 2170 2171 2171 2172 static const struct proto_ops hci_sock_ops = {
+1 -1
net/bluetooth/hci_sync.c
··· 4592 4592 { 4593 4593 int err; 4594 4594 4595 - if (iso_capable(hdev)) { 4595 + if (cis_capable(hdev)) { 4596 4596 /* Connected Isochronous Channels (Host Support) */ 4597 4597 err = hci_le_set_host_feature_sync(hdev, 32, 4598 4598 (iso_enabled(hdev) ? 0x01 :
+1
net/bluetooth/iso.c
··· 746 746 747 747 skb_queue_purge(&sk->sk_receive_queue); 748 748 skb_queue_purge(&sk->sk_write_queue); 749 + skb_queue_purge(&sk->sk_error_queue); 749 750 } 750 751 751 752 static void iso_sock_cleanup_listen(struct sock *parent)
+74 -29
net/bluetooth/l2cap_core.c
··· 4916 4916 goto response_unlock; 4917 4917 } 4918 4918 4919 + /* Check if Key Size is sufficient for the security level */ 4920 + if (!l2cap_check_enc_key_size(conn->hcon, pchan)) { 4921 + result = L2CAP_CR_LE_BAD_KEY_SIZE; 4922 + chan = NULL; 4923 + goto response_unlock; 4924 + } 4925 + 4919 4926 /* Check for valid dynamic CID range */ 4920 4927 if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { 4921 4928 result = L2CAP_CR_LE_INVALID_SCID; ··· 5058 5051 struct l2cap_chan *chan, *pchan; 5059 5052 u16 mtu, mps; 5060 5053 __le16 psm; 5061 - u8 result, len = 0; 5054 + u8 result, rsp_len = 0; 5062 5055 int i, num_scid; 5063 5056 bool defer = false; 5064 5057 5065 5058 if (!enable_ecred) 5066 5059 return -EINVAL; 5060 + 5061 + memset(pdu, 0, sizeof(*pdu)); 5067 5062 5068 5063 if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) { 5069 5064 result = L2CAP_CR_LE_INVALID_PARAMS; ··· 5074 5065 5075 5066 cmd_len -= sizeof(*req); 5076 5067 num_scid = cmd_len / sizeof(u16); 5068 + 5069 + /* Always respond with the same number of scids as in the request */ 5070 + rsp_len = cmd_len; 5077 5071 5078 5072 if (num_scid > L2CAP_ECRED_MAX_CID) { 5079 5073 result = L2CAP_CR_LE_INVALID_PARAMS; ··· 5087 5075 mps = __le16_to_cpu(req->mps); 5088 5076 5089 5077 if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) { 5090 - result = L2CAP_CR_LE_UNACCEPT_PARAMS; 5078 + result = L2CAP_CR_LE_INVALID_PARAMS; 5091 5079 goto response; 5092 5080 } 5093 5081 ··· 5107 5095 5108 5096 BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps); 5109 5097 5110 - memset(pdu, 0, sizeof(*pdu)); 5111 - 5112 5098 /* Check if we have socket listening on psm */ 5113 5099 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, 5114 5100 &conn->hcon->dst, LE_LINK); ··· 5119 5109 5120 5110 if (!smp_sufficient_security(conn->hcon, pchan->sec_level, 5121 5111 SMP_ALLOW_STK)) { 5122 - result = L2CAP_CR_LE_AUTHENTICATION; 5112 + result = pchan->sec_level == BT_SECURITY_MEDIUM ? 5113 + L2CAP_CR_LE_ENCRYPTION : L2CAP_CR_LE_AUTHENTICATION; 5114 + goto unlock; 5115 + } 5116 + 5117 + /* Check if the listening channel has set an output MTU then the 5118 + * requested MTU shall be less than or equal to that value. 5119 + */ 5120 + if (pchan->omtu && mtu < pchan->omtu) { 5121 + result = L2CAP_CR_LE_UNACCEPT_PARAMS; 5123 5122 goto unlock; 5124 5123 } 5125 5124 ··· 5140 5121 BT_DBG("scid[%d] 0x%4.4x", i, scid); 5141 5122 5142 5123 pdu->dcid[i] = 0x0000; 5143 - len += sizeof(*pdu->dcid); 5144 5124 5145 5125 /* Check for valid dynamic CID range */ 5146 5126 if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { ··· 5206 5188 return 0; 5207 5189 5208 5190 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP, 5209 - sizeof(*pdu) + len, pdu); 5191 + sizeof(*pdu) + rsp_len, pdu); 5210 5192 5211 5193 return 0; 5212 5194 } ··· 5328 5310 struct l2cap_ecred_reconf_req *req = (void *) data; 5329 5311 struct l2cap_ecred_reconf_rsp rsp; 5330 5312 u16 mtu, mps, result; 5331 - struct l2cap_chan *chan; 5313 + struct l2cap_chan *chan[L2CAP_ECRED_MAX_CID] = {}; 5332 5314 int i, num_scid; 5333 5315 5334 5316 if (!enable_ecred) 5335 5317 return -EINVAL; 5336 5318 5337 - if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) { 5338 - result = L2CAP_CR_LE_INVALID_PARAMS; 5319 + if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) { 5320 + result = L2CAP_RECONF_INVALID_CID; 5339 5321 goto respond; 5340 5322 } 5341 5323 ··· 5345 5327 BT_DBG("mtu %u mps %u", mtu, mps); 5346 5328 5347 5329 if (mtu < L2CAP_ECRED_MIN_MTU) { 5348 - result = L2CAP_RECONF_INVALID_MTU; 5330 + result = L2CAP_RECONF_INVALID_PARAMS; 5349 5331 goto respond; 5350 5332 } 5351 5333 5352 5334 if (mps < L2CAP_ECRED_MIN_MPS) { 5353 - result = L2CAP_RECONF_INVALID_MPS; 5335 + result = L2CAP_RECONF_INVALID_PARAMS; 5354 5336 goto respond; 5355 5337 } 5356 5338 5357 5339 cmd_len -= sizeof(*req); 5358 5340 num_scid = cmd_len / sizeof(u16); 5341 + 5342 + if (num_scid > L2CAP_ECRED_MAX_CID) { 5343 + result = L2CAP_RECONF_INVALID_PARAMS; 5344 + goto respond; 5345 + } 5346 + 5359 5347 result = L2CAP_RECONF_SUCCESS; 5360 5348 5349 + /* Check if each SCID, MTU and MPS are valid */ 5361 5350 for (i = 0; i < num_scid; i++) { 5362 5351 u16 scid; 5363 5352 5364 5353 scid = __le16_to_cpu(req->scid[i]); 5365 - if (!scid) 5366 - return -EPROTO; 5367 - 5368 - chan = __l2cap_get_chan_by_dcid(conn, scid); 5369 - if (!chan) 5370 - continue; 5371 - 5372 - /* If the MTU value is decreased for any of the included 5373 - * channels, then the receiver shall disconnect all 5374 - * included channels. 5375 - */ 5376 - if (chan->omtu > mtu) { 5377 - BT_ERR("chan %p decreased MTU %u -> %u", chan, 5378 - chan->omtu, mtu); 5379 - result = L2CAP_RECONF_INVALID_MTU; 5354 + if (!scid) { 5355 + result = L2CAP_RECONF_INVALID_CID; 5356 + goto respond; 5380 5357 } 5381 5358 5382 - chan->omtu = mtu; 5383 - chan->remote_mps = mps; 5359 + chan[i] = __l2cap_get_chan_by_dcid(conn, scid); 5360 + if (!chan[i]) { 5361 + result = L2CAP_RECONF_INVALID_CID; 5362 + goto respond; 5363 + } 5364 + 5365 + /* The MTU field shall be greater than or equal to the greatest 5366 + * current MTU size of these channels. 5367 + */ 5368 + if (chan[i]->omtu > mtu) { 5369 + BT_ERR("chan %p decreased MTU %u -> %u", chan[i], 5370 + chan[i]->omtu, mtu); 5371 + result = L2CAP_RECONF_INVALID_MTU; 5372 + goto respond; 5373 + } 5374 + 5375 + /* If more than one channel is being configured, the MPS field 5376 + * shall be greater than or equal to the current MPS size of 5377 + * each of these channels. If only one channel is being 5378 + * configured, the MPS field may be less than the current MPS 5379 + * of that channel. 5380 + */ 5381 + if (chan[i]->remote_mps >= mps && i) { 5382 + BT_ERR("chan %p decreased MPS %u -> %u", chan[i], 5383 + chan[i]->remote_mps, mps); 5384 + result = L2CAP_RECONF_INVALID_MPS; 5385 + goto respond; 5386 + } 5387 + } 5388 + 5389 + /* Commit the new MTU and MPS values after checking they are valid */ 5390 + for (i = 0; i < num_scid; i++) { 5391 + chan[i]->omtu = mtu; 5392 + chan[i]->remote_mps = mps; 5384 5393 } 5385 5394 5386 5395 respond:
+12 -4
net/bluetooth/l2cap_sock.c
··· 1029 1029 break; 1030 1030 } 1031 1031 1032 - /* Setting is not supported as it's the remote side that 1033 - * decides this. 1034 - */ 1035 - err = -EPERM; 1032 + /* Only allow setting output MTU when not connected */ 1033 + if (sk->sk_state == BT_CONNECTED) { 1034 + err = -EISCONN; 1035 + break; 1036 + } 1037 + 1038 + err = copy_safe_from_sockptr(&mtu, sizeof(mtu), optval, optlen); 1039 + if (err) 1040 + break; 1041 + 1042 + chan->omtu = mtu; 1036 1043 break; 1037 1044 1038 1045 case BT_RCVMTU: ··· 1824 1817 1825 1818 skb_queue_purge(&sk->sk_receive_queue); 1826 1819 skb_queue_purge(&sk->sk_write_queue); 1820 + skb_queue_purge(&sk->sk_error_queue); 1827 1821 } 1828 1822 1829 1823 static void l2cap_skb_msg_name(struct sk_buff *skb, void *msg_name,
+1
net/bluetooth/sco.c
··· 470 470 471 471 skb_queue_purge(&sk->sk_receive_queue); 472 472 skb_queue_purge(&sk->sk_write_queue); 473 + skb_queue_purge(&sk->sk_error_queue); 473 474 } 474 475 475 476 static void sco_sock_cleanup_listen(struct sock *parent)