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

Commit 09627330 authored by David S. Miller's avatar David S. Miller
Browse files


Johan Hedberg says:

====================
pull request: bluetooth 2015-11-05

The following set of Bluetooth patches would be good to get into 4.4-rc1
if possible:

 - Fix for missing LE CoC parameter validity checks
 - Fix for potential deadlock in btusb
 - Fix for issuing unsupported commands during HCI init

Please let me know if there are any issues pulling. Thanks.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d4e4bc16 40624183
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -1372,6 +1372,8 @@ static void btusb_work(struct work_struct *work)
		}

		if (data->isoc_altsetting != new_alts) {
			unsigned long flags;

			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
			usb_kill_anchored_urbs(&data->isoc_anchor);

@@ -1384,10 +1386,10 @@ static void btusb_work(struct work_struct *work)
			 * Clear outstanding fragment when selecting a new
			 * alternate setting.
			 */
			spin_lock(&data->rxlock);
			spin_lock_irqsave(&data->rxlock, flags);
			kfree_skb(data->sco_skb);
			data->sco_skb = NULL;
			spin_unlock(&data->rxlock);
			spin_unlock_irqrestore(&data->rxlock, flags);

			if (__set_isoc_interface(hdev, new_alts) < 0)
				return;
+2 −0
Original line number Diff line number Diff line
@@ -275,6 +275,8 @@ struct l2cap_conn_rsp {
#define L2CAP_CR_AUTHORIZATION	0x0006
#define L2CAP_CR_BAD_KEY_SIZE	0x0007
#define L2CAP_CR_ENCRYPTION	0x0008
#define L2CAP_CR_INVALID_SCID	0x0009
#define L2CAP_CR_SCID_IN_USE	0x0010

/* connect/create channel status */
#define L2CAP_CS_NO_INFO	0x0000
+11 −6
Original line number Diff line number Diff line
@@ -508,12 +508,6 @@ static void le_setup(struct hci_request *req)
	/* Read LE Supported States */
	hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);

	/* Read LE White List Size */
	hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);

	/* Clear LE White List */
	hci_req_add(req, HCI_OP_LE_CLEAR_WHITE_LIST, 0, NULL);

	/* LE-only controllers have LE implicitly enabled */
	if (!lmp_bredr_capable(hdev))
		hci_dev_set_flag(hdev, HCI_LE_ENABLED);
@@ -832,6 +826,17 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
			hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
		}

		if (hdev->commands[26] & 0x40) {
			/* Read LE White List Size */
			hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE,
				    0, NULL);
		}

		if (hdev->commands[26] & 0x80) {
			/* Clear LE White List */
			hci_req_add(req, HCI_OP_LE_CLEAR_WHITE_LIST, 0, NULL);
		}

		if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) {
			/* Read LE Maximum Data Length */
			hci_req_add(req, HCI_OP_LE_READ_MAX_DATA_LEN, 0, NULL);
+17 −3
Original line number Diff line number Diff line
@@ -239,7 +239,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
	else
		dyn_end = L2CAP_CID_DYN_END;

	for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) {
	for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
		if (!__l2cap_get_chan_by_scid(conn, cid))
			return cid;
	}
@@ -5250,7 +5250,9 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
	credits = __le16_to_cpu(rsp->credits);
	result  = __le16_to_cpu(rsp->result);

	if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23))
	if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23 ||
					   dcid < L2CAP_CID_DYN_START ||
					   dcid > L2CAP_CID_LE_DYN_END))
		return -EPROTO;

	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
@@ -5270,6 +5272,11 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,

	switch (result) {
	case L2CAP_CR_SUCCESS:
		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
			err = -EBADSLT;
			break;
		}

		chan->ident = 0;
		chan->dcid = dcid;
		chan->omtu = mtu;
@@ -5437,9 +5444,16 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
		goto response_unlock;
	}

	/* Check for valid dynamic CID range */
	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
		result = L2CAP_CR_INVALID_SCID;
		chan = NULL;
		goto response_unlock;
	}

	/* Check if we already have channel with that dcid */
	if (__l2cap_get_chan_by_dcid(conn, scid)) {
		result = L2CAP_CR_NO_MEM;
		result = L2CAP_CR_SCID_IN_USE;
		chan = NULL;
		goto response_unlock;
	}