2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-15 08:44:14 +08:00

Bluetooth: Only one command per L2CAP LE signalling is supported

The Bluetooth specification makes it clear that only one command
should be present in the L2CAP LE signalling packet. So tighten
the checks here and restrict it to exactly one command.

This is different from L2CAP BR/EDR signalling where multiple
commands can be part of the same packet.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Marcel Holtmann 2013-10-03 01:26:37 -07:00 committed by Johan Hedberg
parent 92381f5cd7
commit 4f3e219d95

View File

@ -5322,43 +5322,37 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct hci_conn *hcon = conn->hcon; struct hci_conn *hcon = conn->hcon;
u8 *data = skb->data; struct l2cap_cmd_hdr *cmd;
int len = skb->len; u16 len;
struct l2cap_cmd_hdr cmd;
int err; int err;
if (hcon->type != LE_LINK) if (hcon->type != LE_LINK)
goto drop; goto drop;
while (len >= L2CAP_CMD_HDR_SIZE) { if (skb->len < L2CAP_CMD_HDR_SIZE)
u16 cmd_len; goto drop;
memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
data += L2CAP_CMD_HDR_SIZE;
len -= L2CAP_CMD_HDR_SIZE;
cmd_len = le16_to_cpu(cmd.len); cmd = (void *) skb->data;
skb_pull(skb, L2CAP_CMD_HDR_SIZE);
BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, len = le16_to_cpu(cmd->len);
cmd.ident);
if (cmd_len > len || !cmd.ident) { BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
BT_DBG("corrupted command");
break;
}
err = l2cap_le_sig_cmd(conn, &cmd, data); if (len != skb->len || !cmd->ident) {
if (err) { BT_DBG("corrupted command");
struct l2cap_cmd_rej_unk rej; goto drop;
}
BT_ERR("Wrong link type (%d)", err); err = l2cap_le_sig_cmd(conn, cmd, skb->data);
if (err) {
struct l2cap_cmd_rej_unk rej;
rej.reason = l2cap_err_to_reason(err); BT_ERR("Wrong link type (%d)", err);
l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
sizeof(rej), &rej);
}
data += cmd_len; rej.reason = l2cap_err_to_reason(err);
len -= cmd_len; l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
sizeof(rej), &rej);
} }
drop: drop: