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

Luiz Augusto von Dentz says:

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

- btusb: use skb_pull to avoid unsafe access in QCA dump handling
- L2CAP: Fix not checking l2cap_chan security level

* tag 'for-net-2025-05-15' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
Bluetooth: btusb: use skb_pull to avoid unsafe access in QCA dump handling
Bluetooth: L2CAP: Fix not checking l2cap_chan security level
====================

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

+48 -65
+40 -58
drivers/bluetooth/btusb.c
··· 3014 3014 static int handle_dump_pkt_qca(struct hci_dev *hdev, struct sk_buff *skb) 3015 3015 { 3016 3016 int ret = 0; 3017 + unsigned int skip = 0; 3017 3018 u8 pkt_type; 3018 - u8 *sk_ptr; 3019 - unsigned int sk_len; 3020 3019 u16 seqno; 3021 3020 u32 dump_size; 3022 3021 ··· 3024 3025 struct usb_device *udev = btdata->udev; 3025 3026 3026 3027 pkt_type = hci_skb_pkt_type(skb); 3027 - sk_ptr = skb->data; 3028 - sk_len = skb->len; 3028 + skip = sizeof(struct hci_event_hdr); 3029 + if (pkt_type == HCI_ACLDATA_PKT) 3030 + skip += sizeof(struct hci_acl_hdr); 3029 3031 3030 - if (pkt_type == HCI_ACLDATA_PKT) { 3031 - sk_ptr += HCI_ACL_HDR_SIZE; 3032 - sk_len -= HCI_ACL_HDR_SIZE; 3033 - } 3032 + skb_pull(skb, skip); 3033 + dump_hdr = (struct qca_dump_hdr *)skb->data; 3034 3034 3035 - sk_ptr += HCI_EVENT_HDR_SIZE; 3036 - sk_len -= HCI_EVENT_HDR_SIZE; 3037 - 3038 - dump_hdr = (struct qca_dump_hdr *)sk_ptr; 3039 3035 seqno = le16_to_cpu(dump_hdr->seqno); 3040 3036 if (seqno == 0) { 3041 3037 set_bit(BTUSB_HW_SSR_ACTIVE, &btdata->flags); ··· 3050 3056 3051 3057 btdata->qca_dump.ram_dump_size = dump_size; 3052 3058 btdata->qca_dump.ram_dump_seqno = 0; 3053 - sk_ptr += offsetof(struct qca_dump_hdr, data0); 3054 - sk_len -= offsetof(struct qca_dump_hdr, data0); 3059 + 3060 + skb_pull(skb, offsetof(struct qca_dump_hdr, data0)); 3055 3061 3056 3062 usb_disable_autosuspend(udev); 3057 3063 bt_dev_info(hdev, "%s memdump size(%u)\n", 3058 3064 (pkt_type == HCI_ACLDATA_PKT) ? "ACL" : "event", 3059 3065 dump_size); 3060 3066 } else { 3061 - sk_ptr += offsetof(struct qca_dump_hdr, data); 3062 - sk_len -= offsetof(struct qca_dump_hdr, data); 3067 + skb_pull(skb, offsetof(struct qca_dump_hdr, data)); 3063 3068 } 3064 3069 3065 3070 if (!btdata->qca_dump.ram_dump_size) { ··· 3078 3085 return ret; 3079 3086 } 3080 3087 3081 - skb_pull(skb, skb->len - sk_len); 3082 3088 hci_devcd_append(hdev, skb); 3083 3089 btdata->qca_dump.ram_dump_seqno++; 3084 3090 if (seqno == QCA_LAST_SEQUENCE_NUM) { ··· 3105 3113 /* Return: true if the ACL packet is a dump packet, false otherwise. */ 3106 3114 static bool acl_pkt_is_dump_qca(struct hci_dev *hdev, struct sk_buff *skb) 3107 3115 { 3108 - u8 *sk_ptr; 3109 - unsigned int sk_len; 3110 - 3111 3116 struct hci_event_hdr *event_hdr; 3112 3117 struct hci_acl_hdr *acl_hdr; 3113 3118 struct qca_dump_hdr *dump_hdr; 3119 + struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); 3120 + bool is_dump = false; 3114 3121 3115 - sk_ptr = skb->data; 3116 - sk_len = skb->len; 3117 - 3118 - acl_hdr = hci_acl_hdr(skb); 3119 - if (le16_to_cpu(acl_hdr->handle) != QCA_MEMDUMP_ACL_HANDLE) 3122 + if (!clone) 3120 3123 return false; 3121 3124 3122 - sk_ptr += HCI_ACL_HDR_SIZE; 3123 - sk_len -= HCI_ACL_HDR_SIZE; 3124 - event_hdr = (struct hci_event_hdr *)sk_ptr; 3125 + acl_hdr = skb_pull_data(clone, sizeof(*acl_hdr)); 3126 + if (!acl_hdr || (le16_to_cpu(acl_hdr->handle) != QCA_MEMDUMP_ACL_HANDLE)) 3127 + goto out; 3125 3128 3126 - if ((event_hdr->evt != HCI_VENDOR_PKT) || 3127 - (event_hdr->plen != (sk_len - HCI_EVENT_HDR_SIZE))) 3128 - return false; 3129 + event_hdr = skb_pull_data(clone, sizeof(*event_hdr)); 3130 + if (!event_hdr || (event_hdr->evt != HCI_VENDOR_PKT)) 3131 + goto out; 3129 3132 3130 - sk_ptr += HCI_EVENT_HDR_SIZE; 3131 - sk_len -= HCI_EVENT_HDR_SIZE; 3133 + dump_hdr = skb_pull_data(clone, sizeof(*dump_hdr)); 3134 + if (!dump_hdr || (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) || 3135 + (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) 3136 + goto out; 3132 3137 3133 - dump_hdr = (struct qca_dump_hdr *)sk_ptr; 3134 - if ((sk_len < offsetof(struct qca_dump_hdr, data)) || 3135 - (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) || 3136 - (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) 3137 - return false; 3138 - 3139 - return true; 3138 + is_dump = true; 3139 + out: 3140 + consume_skb(clone); 3141 + return is_dump; 3140 3142 } 3141 3143 3142 3144 /* Return: true if the event packet is a dump packet, false otherwise. */ 3143 3145 static bool evt_pkt_is_dump_qca(struct hci_dev *hdev, struct sk_buff *skb) 3144 3146 { 3145 - u8 *sk_ptr; 3146 - unsigned int sk_len; 3147 - 3148 3147 struct hci_event_hdr *event_hdr; 3149 3148 struct qca_dump_hdr *dump_hdr; 3149 + struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); 3150 + bool is_dump = false; 3150 3151 3151 - sk_ptr = skb->data; 3152 - sk_len = skb->len; 3153 - 3154 - event_hdr = hci_event_hdr(skb); 3155 - 3156 - if ((event_hdr->evt != HCI_VENDOR_PKT) 3157 - || (event_hdr->plen != (sk_len - HCI_EVENT_HDR_SIZE))) 3152 + if (!clone) 3158 3153 return false; 3159 3154 3160 - sk_ptr += HCI_EVENT_HDR_SIZE; 3161 - sk_len -= HCI_EVENT_HDR_SIZE; 3155 + event_hdr = skb_pull_data(clone, sizeof(*event_hdr)); 3156 + if (!event_hdr || (event_hdr->evt != HCI_VENDOR_PKT)) 3157 + goto out; 3162 3158 3163 - dump_hdr = (struct qca_dump_hdr *)sk_ptr; 3164 - if ((sk_len < offsetof(struct qca_dump_hdr, data)) || 3165 - (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) || 3166 - (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) 3167 - return false; 3159 + dump_hdr = skb_pull_data(clone, sizeof(*dump_hdr)); 3160 + if (!dump_hdr || (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) || 3161 + (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) 3162 + goto out; 3168 3163 3169 - return true; 3164 + is_dump = true; 3165 + out: 3166 + consume_skb(clone); 3167 + return is_dump; 3170 3168 } 3171 3169 3172 3170 static int btusb_recv_acl_qca(struct hci_dev *hdev, struct sk_buff *skb)
+8 -7
net/bluetooth/l2cap_core.c
··· 1411 1411 sizeof(req), &req); 1412 1412 } 1413 1413 1414 - static bool l2cap_check_enc_key_size(struct hci_conn *hcon) 1414 + static bool l2cap_check_enc_key_size(struct hci_conn *hcon, 1415 + struct l2cap_chan *chan) 1415 1416 { 1416 1417 /* The minimum encryption key size needs to be enforced by the 1417 1418 * host stack before establishing any L2CAP connections. The ··· 1426 1425 int min_key_size = hcon->hdev->min_enc_key_size; 1427 1426 1428 1427 /* On FIPS security level, key size must be 16 bytes */ 1429 - if (hcon->sec_level == BT_SECURITY_FIPS) 1428 + if (chan->sec_level == BT_SECURITY_FIPS) 1430 1429 min_key_size = 16; 1431 1430 1432 1431 return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || ··· 1454 1453 !__l2cap_no_conn_pending(chan)) 1455 1454 return; 1456 1455 1457 - if (l2cap_check_enc_key_size(conn->hcon)) 1456 + if (l2cap_check_enc_key_size(conn->hcon, chan)) 1458 1457 l2cap_start_connection(chan); 1459 1458 else 1460 1459 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); ··· 1529 1528 continue; 1530 1529 } 1531 1530 1532 - if (l2cap_check_enc_key_size(conn->hcon)) 1531 + if (l2cap_check_enc_key_size(conn->hcon, chan)) 1533 1532 l2cap_start_connection(chan); 1534 1533 else 1535 1534 l2cap_chan_close(chan, ECONNREFUSED); ··· 3993 3992 /* Check if the ACL is secure enough (if not SDP) */ 3994 3993 if (psm != cpu_to_le16(L2CAP_PSM_SDP) && 3995 3994 (!hci_conn_check_link_mode(conn->hcon) || 3996 - !l2cap_check_enc_key_size(conn->hcon))) { 3995 + !l2cap_check_enc_key_size(conn->hcon, pchan))) { 3997 3996 conn->disc_reason = HCI_ERROR_AUTH_FAILURE; 3998 3997 result = L2CAP_CR_SEC_BLOCK; 3999 3998 goto response; ··· 7353 7352 } 7354 7353 7355 7354 if (chan->state == BT_CONNECT) { 7356 - if (!status && l2cap_check_enc_key_size(hcon)) 7355 + if (!status && l2cap_check_enc_key_size(hcon, chan)) 7357 7356 l2cap_start_connection(chan); 7358 7357 else 7359 7358 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); ··· 7363 7362 struct l2cap_conn_rsp rsp; 7364 7363 __u16 res, stat; 7365 7364 7366 - if (!status && l2cap_check_enc_key_size(hcon)) { 7365 + if (!status && l2cap_check_enc_key_size(hcon, chan)) { 7367 7366 if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { 7368 7367 res = L2CAP_CR_PEND; 7369 7368 stat = L2CAP_CS_AUTHOR_PEND;