Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f3e219d authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Johan Hedberg
Browse files

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: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent 92381f5c
Loading
Loading
Loading
Loading
+19 −25
Original line number Diff line number Diff line
@@ -5322,45 +5322,39 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
					struct sk_buff *skb)
{
	struct hci_conn *hcon = conn->hcon;
	u8 *data = skb->data;
	int len = skb->len;
	struct l2cap_cmd_hdr cmd;
	struct l2cap_cmd_hdr *cmd;
	u16 len;
	int err;

	if (hcon->type != LE_LINK)
		goto drop;

	while (len >= L2CAP_CMD_HDR_SIZE) {
		u16 cmd_len;
		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
		data += L2CAP_CMD_HDR_SIZE;
		len  -= L2CAP_CMD_HDR_SIZE;
	if (skb->len < L2CAP_CMD_HDR_SIZE)
		goto drop;

		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,
		       cmd.ident);
	len = le16_to_cpu(cmd->len);

		if (cmd_len > len || !cmd.ident) {
	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);

	if (len != skb->len || !cmd->ident) {
		BT_DBG("corrupted command");
			break;
		goto drop;
	}

		err = l2cap_le_sig_cmd(conn, &cmd, data);
	err = l2cap_le_sig_cmd(conn, cmd, skb->data);
	if (err) {
		struct l2cap_cmd_rej_unk rej;

		BT_ERR("Wrong link type (%d)", err);

		rej.reason = l2cap_err_to_reason(err);
			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
			       sizeof(rej), &rej);
	}

		data += cmd_len;
		len  -= cmd_len;
	}

drop:
	kfree_skb(skb);
}