[PATCH v3 RESEND 1/3] Bluetooth: btmtk: drop zero-length ISO packets from endpoint padding

Chris Lu chris.lu at mediatek.com
Wed Oct 21 01:43:35 PDT 2026


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. Confirm that the rest of the transfer is
zero-filled before dropping it, since the padding runs to the end of the
transfer.

This was observed on MT7925, but btmtk_recv_isopkt() is shared by every
MediaTek USB controller that supports ISO data.

Fixes: ceac1cb0259d ("Bluetooth: btusb: mediatek: add ISO data transmission functions")
Co-developed-by: Hao Qin <hao.qin at mediatek.com>
Signed-off-by: Hao Qin <hao.qin at mediatek.com>
Co-developed-by: Wenlong Tian <ot_wenlong.tian at mediatek.com>
Signed-off-by: Wenlong Tian <ot_wenlong.tian at mediatek.com>
Signed-off-by: Chris Lu <chris.lu at mediatek.com>
---
 drivers/bluetooth/btmtk.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 75483d8230e1..90463208385b 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -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>
@@ -1588,6 +1589,25 @@ 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)) {
+				/* The interrupt endpoint zero-fills the
+				 * remainder of the transfer after the one
+				 * packet it carries. Confirm that is what
+				 * this is before dropping it.
+				 */
+				if (!mem_is_zero(buffer, count)) {
+					kfree_skb(skb);
+					skb = NULL;
+
+					err = -EILSEQ;
+					break;
+				}
+
+				kfree_skb(skb);
+				skb = NULL;
+				break;
+			}
+
 			if (skb_tailroom(skb) < hci_skb_expect(skb)) {
 				kfree_skb(skb);
 				skb = NULL;
-- 
2.45.2




More information about the Linux-mediatek mailing list