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

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth

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
...@@ -1372,6 +1372,8 @@ static void btusb_work(struct work_struct *work) ...@@ -1372,6 +1372,8 @@ static void btusb_work(struct work_struct *work)
} }
if (data->isoc_altsetting != new_alts) { if (data->isoc_altsetting != new_alts) {
unsigned long flags;
clear_bit(BTUSB_ISOC_RUNNING, &data->flags); clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
usb_kill_anchored_urbs(&data->isoc_anchor); usb_kill_anchored_urbs(&data->isoc_anchor);
...@@ -1384,10 +1386,10 @@ static void btusb_work(struct work_struct *work) ...@@ -1384,10 +1386,10 @@ static void btusb_work(struct work_struct *work)
* Clear outstanding fragment when selecting a new * Clear outstanding fragment when selecting a new
* alternate setting. * alternate setting.
*/ */
spin_lock(&data->rxlock); spin_lock_irqsave(&data->rxlock, flags);
kfree_skb(data->sco_skb); kfree_skb(data->sco_skb);
data->sco_skb = NULL; data->sco_skb = NULL;
spin_unlock(&data->rxlock); spin_unlock_irqrestore(&data->rxlock, flags);
if (__set_isoc_interface(hdev, new_alts) < 0) if (__set_isoc_interface(hdev, new_alts) < 0)
return; return;
......
...@@ -275,6 +275,8 @@ struct l2cap_conn_rsp { ...@@ -275,6 +275,8 @@ struct l2cap_conn_rsp {
#define L2CAP_CR_AUTHORIZATION 0x0006 #define L2CAP_CR_AUTHORIZATION 0x0006
#define L2CAP_CR_BAD_KEY_SIZE 0x0007 #define L2CAP_CR_BAD_KEY_SIZE 0x0007
#define L2CAP_CR_ENCRYPTION 0x0008 #define L2CAP_CR_ENCRYPTION 0x0008
#define L2CAP_CR_INVALID_SCID 0x0009
#define L2CAP_CR_SCID_IN_USE 0x0010
/* connect/create channel status */ /* connect/create channel status */
#define L2CAP_CS_NO_INFO 0x0000 #define L2CAP_CS_NO_INFO 0x0000
......
...@@ -508,12 +508,6 @@ static void le_setup(struct hci_request *req) ...@@ -508,12 +508,6 @@ static void le_setup(struct hci_request *req)
/* Read LE Supported States */ /* Read LE Supported States */
hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); 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 */ /* LE-only controllers have LE implicitly enabled */
if (!lmp_bredr_capable(hdev)) if (!lmp_bredr_capable(hdev))
hci_dev_set_flag(hdev, HCI_LE_ENABLED); hci_dev_set_flag(hdev, HCI_LE_ENABLED);
...@@ -832,6 +826,17 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) ...@@ -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); 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) { if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) {
/* Read LE Maximum Data Length */ /* Read LE Maximum Data Length */
hci_req_add(req, HCI_OP_LE_READ_MAX_DATA_LEN, 0, NULL); hci_req_add(req, HCI_OP_LE_READ_MAX_DATA_LEN, 0, NULL);
......
...@@ -239,7 +239,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) ...@@ -239,7 +239,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
else else
dyn_end = L2CAP_CID_DYN_END; 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)) if (!__l2cap_get_chan_by_scid(conn, cid))
return cid; return cid;
} }
...@@ -5250,7 +5250,9 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn, ...@@ -5250,7 +5250,9 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
credits = __le16_to_cpu(rsp->credits); credits = __le16_to_cpu(rsp->credits);
result = __le16_to_cpu(rsp->result); 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; return -EPROTO;
BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", 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, ...@@ -5270,6 +5272,11 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
switch (result) { switch (result) {
case L2CAP_CR_SUCCESS: case L2CAP_CR_SUCCESS:
if (__l2cap_get_chan_by_dcid(conn, dcid)) {
err = -EBADSLT;
break;
}
chan->ident = 0; chan->ident = 0;
chan->dcid = dcid; chan->dcid = dcid;
chan->omtu = mtu; chan->omtu = mtu;
...@@ -5437,9 +5444,16 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, ...@@ -5437,9 +5444,16 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
goto response_unlock; 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 */ /* Check if we already have channel with that dcid */
if (__l2cap_get_chan_by_dcid(conn, scid)) { if (__l2cap_get_chan_by_dcid(conn, scid)) {
result = L2CAP_CR_NO_MEM; result = L2CAP_CR_SCID_IN_USE;
chan = NULL; chan = NULL;
goto response_unlock; goto response_unlock;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment