Bluetooth: L2CAP: Send reject on command corrupted request
authorFrédéric Danis <frederic.danis@collabora.com>
Fri, 8 Dec 2023 17:41:50 +0000 (18:41 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Jan 2024 12:42:40 +0000 (12:42 +0000)
commit 78b99eb1faa7371bf9c534690f26a71b6996622d upstream.

L2CAP/COS/CED/BI-02-C PTS test send a malformed L2CAP signaling packet
with 2 commands in it (a connection request and an unknown command) and
expect to get a connection response packet and a command reject packet.
The second is currently not sent.

Cc: stable@vger.kernel.org
Signed-off-by: Frédéric Danis <frederic.danis@collabora.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/bluetooth/l2cap_core.c

index 17ca13e..baeebee 100644 (file)
@@ -6492,6 +6492,14 @@ drop:
        kfree_skb(skb);
 }
 
+static inline void l2cap_sig_send_rej(struct l2cap_conn *conn, u16 ident)
+{
+       struct l2cap_cmd_rej_unk rej;
+
+       rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
+       l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
+}
+
 static inline void l2cap_sig_channel(struct l2cap_conn *conn,
                                     struct sk_buff *skb)
 {
@@ -6517,23 +6525,24 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
 
                if (len > skb->len || !cmd->ident) {
                        BT_DBG("corrupted command");
+                       l2cap_sig_send_rej(conn, cmd->ident);
                        break;
                }
 
                err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data);
                if (err) {
-                       struct l2cap_cmd_rej_unk rej;
-
                        BT_ERR("Wrong link type (%d)", err);
-
-                       rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
-                       l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
-                                      sizeof(rej), &rej);
+                       l2cap_sig_send_rej(conn, cmd->ident);
                }
 
                skb_pull(skb, len);
        }
 
+       if (skb->len > 0) {
+               BT_DBG("corrupted command");
+               l2cap_sig_send_rej(conn, 0);
+       }
+
 drop:
        kfree_skb(skb);
 }