summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaxman Acharya Padhya <acharyalaxman8848@gmail.com>2026-08-24 21:42:36 +0545
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2026-09-15 14:52:12 -0400
commitd0795cfd6f655f4de84868a4f4bb41a03f037b3d (patch)
treec9f512b876be54e1ce317c33b114cdfad08946ad
parent4914c499896121ae8b9d5b90f0abc5c8287ff396 (diff)
downloadlinux-next-d0795cfd6f655f4de84868a4f4bb41a03f037b3d.tar.gz
linux-next-d0795cfd6f655f4de84868a4f4bb41a03f037b3d.zip
Bluetooth: hci_codec: validate vendor codec count length
The Read Local Supported Codecs parsers consume the variable-sized standard codec array before parsing the vendor codec count. Although the initial reply-size check includes a vendor count byte in the fixed layout, it does not guarantee that the byte remains after the standard codec array. If a controller reply ends immediately after that array, calculating the vendor codec array size reads vnd_codecs->num beyond the skb data. Use skb_pull_data() to validate and consume each codec header before using its count in both command variants. Fixes: 8961987f3f5f ("Bluetooth: Enumerate local supported codec and cache details") Fixes: 9ae664028a9e ("Bluetooth: Add support for Read Local Supported Codecs V2") Cc: stable@vger.kernel.org Suggested-by: Luiz Augusto von Dentz <luiz.dentz@gmail.com> Signed-off-by: Laxman Acharya Padhya <acharyalaxman8848@gmail.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-rw-r--r--net/bluetooth/hci_codec.c36
1 files changed, 18 insertions, 18 deletions
diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c
index 5bc5003c387c..7a7e813dcdda 100644
--- a/net/bluetooth/hci_codec.c
+++ b/net/bluetooth/hci_codec.c
@@ -145,11 +145,12 @@ void hci_read_supported_codecs(struct hci_dev *hdev)
skb_pull(skb, sizeof(rp->status));
- std_codecs = (void *)skb->data;
+ std_codecs = skb_pull_data(skb, sizeof(*std_codecs));
+ if (!std_codecs)
+ goto error;
/* validate codecs length before accessing */
- if (skb->len < flex_array_size(std_codecs, codec, std_codecs->num)
- + sizeof(std_codecs->num))
+ if (skb->len < flex_array_size(std_codecs, codec, std_codecs->num))
goto error;
/* enumerate codec capabilities of standard codecs */
@@ -161,15 +162,14 @@ void hci_read_supported_codecs(struct hci_dev *hdev)
LOCAL_CODEC_ACL_MASK | LOCAL_CODEC_SCO_MASK, &caps);
}
- skb_pull(skb, flex_array_size(std_codecs, codec, std_codecs->num)
- + sizeof(std_codecs->num));
+ skb_pull(skb, flex_array_size(std_codecs, codec, std_codecs->num));
- vnd_codecs = (void *)skb->data;
+ vnd_codecs = skb_pull_data(skb, sizeof(*vnd_codecs));
+ if (!vnd_codecs)
+ goto error;
/* validate vendor codecs length before accessing */
- if (skb->len <
- flex_array_size(vnd_codecs, codec, vnd_codecs->num)
- + sizeof(vnd_codecs->num))
+ if (skb->len < flex_array_size(vnd_codecs, codec, vnd_codecs->num))
goto error;
/* enumerate vendor codec capabilities */
@@ -214,11 +214,12 @@ void hci_read_supported_codecs_v2(struct hci_dev *hdev)
skb_pull(skb, sizeof(rp->status));
- std_codecs = (void *)skb->data;
+ std_codecs = skb_pull_data(skb, sizeof(*std_codecs));
+ if (!std_codecs)
+ goto error;
/* check for payload data length before accessing */
- if (skb->len < flex_array_size(std_codecs, codec, std_codecs->num)
- + sizeof(std_codecs->num))
+ if (skb->len < flex_array_size(std_codecs, codec, std_codecs->num))
goto error;
memset(&caps, 0, sizeof(caps));
@@ -229,15 +230,14 @@ void hci_read_supported_codecs_v2(struct hci_dev *hdev)
&caps);
}
- skb_pull(skb, flex_array_size(std_codecs, codec, std_codecs->num)
- + sizeof(std_codecs->num));
+ skb_pull(skb, flex_array_size(std_codecs, codec, std_codecs->num));
- vnd_codecs = (void *)skb->data;
+ vnd_codecs = skb_pull_data(skb, sizeof(*vnd_codecs));
+ if (!vnd_codecs)
+ goto error;
/* check for payload data length before accessing */
- if (skb->len <
- flex_array_size(vnd_codecs, codec, vnd_codecs->num)
- + sizeof(vnd_codecs->num))
+ if (skb->len < flex_array_size(vnd_codecs, codec, vnd_codecs->num))
goto error;
for (i = 0; i < vnd_codecs->num; i++) {