mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
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:8961987f3f("Bluetooth: Enumerate local supported codec and cache details") Fixes:9ae664028a("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>
This commit is contained in:
parent
4914c49989
commit
d0795cfd6f
|
|
@ -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++) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user