mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Bluetooth: btmtk: drop zero-length ISO packets from endpoint padding
The ISO interrupt IN endpoint delivers a fixed-size transfer that holds
one HCI ISO packet and zero-fills the remainder. That padding belongs to
the transfer rather than to the stream, so it has to be dropped instead of
reported to the host.
btmtk_recv_isopkt() keeps parsing it: the zero bytes read as an ISO header
with handle 0 and a Data_Total_Length of zero, and each one is passed to
hci_recv_frame() as a complete frame. A single transfer yields a long run
of them, which is what fills the HCI log with malformed ISO packets, and
iso_recv() drops the SDU it is reassembling whenever handle 0 belongs to a
live CIS/BIS.
A zero Data_Total_Length carries no ISO Data Load, so such a packet is
never part of the stream. Check for the zero-filled remainder before
starting to parse the next frame, rather than after assembling a 4-byte
header: a remainder shorter than HCI_ISO_HDR_SIZE would otherwise be held
across calls as a partial header, corrupting the next transfer's framing.
This also means a fully zero-filled remainder no longer costs an skb
allocation that gets immediately freed. Reaching a zero Data_Total_Length
any other way is then a genuine error, not padding.
This was observed on MT7925, but btmtk_recv_isopkt() is shared by every
MediaTek USB controller that supports ISO data.
Fixes: ceac1cb025 ("Bluetooth: btusb: mediatek: add ISO data transmission functions")
Co-developed-by: Hao Qin <hao.qin@mediatek.com>
Signed-off-by: Hao Qin <hao.qin@mediatek.com>
Co-developed-by: Wenlong Tian <ot_wenlong.tian@mediatek.com>
Signed-off-by: Wenlong Tian <ot_wenlong.tian@mediatek.com>
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
e24bfbc5e2
commit
8524c3588f
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/usb.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
|
@ -1565,6 +1566,14 @@ static int btmtk_recv_isopkt(struct hci_dev *hdev, void *buffer, int count)
|
|||
int len;
|
||||
|
||||
if (!skb) {
|
||||
/* Drop the endpoint's zero-filled padding before
|
||||
* allocating an skb for it; a zero Data_Total_Length
|
||||
* check below would miss a padding remainder
|
||||
* shorter than an ISO header.
|
||||
*/
|
||||
if (mem_is_zero(buffer, count))
|
||||
break;
|
||||
|
||||
skb = bt_skb_alloc(HCI_MAX_ISO_SIZE, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
err = -ENOMEM;
|
||||
|
|
@ -1588,6 +1597,17 @@ static int btmtk_recv_isopkt(struct hci_dev *hdev, void *buffer, int count)
|
|||
/* Complete ISO header */
|
||||
hci_skb_expect(skb) = __le16_to_cpu(dlen);
|
||||
|
||||
if (!hci_skb_expect(skb)) {
|
||||
/* Zero padding was ruled out above, so a
|
||||
* zero Data_Total_Length here is invalid.
|
||||
*/
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
|
||||
err = -EILSEQ;
|
||||
break;
|
||||
}
|
||||
|
||||
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user