net/bluetooth/iso.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
A malformed ISO_END fragment can trigger a NULL pointer dereference
due to missing validation before processing. An oversized end fragment
should also be rejected.
Add the same validation for ISO_END as for ISO_CONT, and reset the
in-progress reassembly state when malformed input is detected.
Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type")
Cc: stable@vger.kernel.org
Signed-off-by: Kangzheng Gu <xiaoguai0992@gmail.com>
---
net/bluetooth/iso.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index be145e2736b7..8707f3c4b103 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -2587,6 +2587,27 @@ int iso_recv(struct hci_dev *hdev, u16 handle, struct sk_buff *skb, u16 flags)
break;
case ISO_END:
+ BT_DBG("End: frag len %d (expecting %d)", skb->len,
+ conn->rx_len);
+
+ if (!conn->rx_len) {
+ BT_ERR("Unexpected end frame (len %d)",
+ skb->len);
+ kfree_skb(conn->rx_skb);
+ conn->rx_skb = NULL;
+ conn->rx_len = 0;
+ goto drop;
+ }
+
+ if (skb->len > conn->rx_len) {
+ BT_ERR("Fragment is too long (len %d, expected %d)",
+ skb->len, conn->rx_len);
+ kfree_skb(conn->rx_skb);
+ conn->rx_skb = NULL;
+ conn->rx_len = 0;
+ goto drop;
+ }
+
skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
skb->len);
conn->rx_len -= skb->len;
--
2.50.1
Hi Kangzheng,
On Sat, Mar 28, 2026 at 4:09 PM Kangzheng Gu <xiaoguai0992@gmail.com> wrote:
>
> A malformed ISO_END fragment can trigger a NULL pointer dereference
> due to missing validation before processing. An oversized end fragment
> should also be rejected.
>
> Add the same validation for ISO_END as for ISO_CONT, and reset the
> in-progress reassembly state when malformed input is detected.
>
> Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type")
> Cc: stable@vger.kernel.org
> Signed-off-by: Kangzheng Gu <xiaoguai0992@gmail.com>
> ---
> net/bluetooth/iso.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
> index be145e2736b7..8707f3c4b103 100644
> --- a/net/bluetooth/iso.c
> +++ b/net/bluetooth/iso.c
> @@ -2587,6 +2587,27 @@ int iso_recv(struct hci_dev *hdev, u16 handle, struct sk_buff *skb, u16 flags)
> break;
>
> case ISO_END:
> + BT_DBG("End: frag len %d (expecting %d)", skb->len,
> + conn->rx_len);
> +
> + if (!conn->rx_len) {
> + BT_ERR("Unexpected end frame (len %d)",
> + skb->len);
> + kfree_skb(conn->rx_skb);
> + conn->rx_skb = NULL;
> + conn->rx_len = 0;
> + goto drop;
> + }
I suspect this was not quite right:
https://sashiko.dev/#/patchset/20260328200938.140528-1-xiaoguai0992%40gmail.com
Have you actually validated this changes against any hardware?
> + if (skb->len > conn->rx_len) {
> + BT_ERR("Fragment is too long (len %d, expected %d)",
> + skb->len, conn->rx_len);
> + kfree_skb(conn->rx_skb);
> + conn->rx_skb = NULL;
> + conn->rx_len = 0;
> + goto drop;
> + }
Hmm, this is the end fragment so anything other than skb->len ==
conn->rx_len is unexpected.
> skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
> skb->len);
> conn->rx_len -= skb->len;
> --
> 2.50.1
>
--
Luiz Augusto von Dentz
© 2016 - 2026 Red Hat, Inc.