mirror of
https://github.com/torvalds/linux.git
synced 2024-11-06 12:11:59 +00:00
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
This commit is contained in:
commit
8b87efba61
@ -90,7 +90,6 @@ static const struct usb_device_id ath3k_table[] = {
|
|||||||
{ USB_DEVICE(0x0b05, 0x17d0) },
|
{ USB_DEVICE(0x0b05, 0x17d0) },
|
||||||
{ USB_DEVICE(0x0CF3, 0x0036) },
|
{ USB_DEVICE(0x0CF3, 0x0036) },
|
||||||
{ USB_DEVICE(0x0CF3, 0x3004) },
|
{ USB_DEVICE(0x0CF3, 0x3004) },
|
||||||
{ USB_DEVICE(0x0CF3, 0x3005) },
|
|
||||||
{ USB_DEVICE(0x0CF3, 0x3008) },
|
{ USB_DEVICE(0x0CF3, 0x3008) },
|
||||||
{ USB_DEVICE(0x0CF3, 0x311D) },
|
{ USB_DEVICE(0x0CF3, 0x311D) },
|
||||||
{ USB_DEVICE(0x0CF3, 0x311E) },
|
{ USB_DEVICE(0x0CF3, 0x311E) },
|
||||||
@ -140,7 +139,6 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||||||
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 },
|
|
||||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
|
||||||
|
@ -162,7 +162,6 @@ static const struct usb_device_id blacklist_table[] = {
|
|||||||
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 },
|
|
||||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
|
||||||
|
@ -406,6 +406,7 @@ static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c)
|
|||||||
H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) {
|
H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) {
|
||||||
BT_ERR("Non-link packet received in non-active state");
|
BT_ERR("Non-link packet received in non-active state");
|
||||||
h5_reset_rx(h5);
|
h5_reset_rx(h5);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h5->rx_func = h5_rx_payload;
|
h5->rx_func = h5_rx_payload;
|
||||||
|
@ -289,10 +289,20 @@ static void hci_conn_timeout(struct work_struct *work)
|
|||||||
{
|
{
|
||||||
struct hci_conn *conn = container_of(work, struct hci_conn,
|
struct hci_conn *conn = container_of(work, struct hci_conn,
|
||||||
disc_work.work);
|
disc_work.work);
|
||||||
|
int refcnt = atomic_read(&conn->refcnt);
|
||||||
|
|
||||||
BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
|
BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
|
||||||
|
|
||||||
if (atomic_read(&conn->refcnt))
|
WARN_ON(refcnt < 0);
|
||||||
|
|
||||||
|
/* FIXME: It was observed that in pairing failed scenario, refcnt
|
||||||
|
* drops below 0. Probably this is because l2cap_conn_del calls
|
||||||
|
* l2cap_chan_del for each channel, and inside l2cap_chan_del conn is
|
||||||
|
* dropped. After that loop hci_chan_del is called which also drops
|
||||||
|
* conn. For now make sure that ACL is alive if refcnt is higher then 0,
|
||||||
|
* otherwise drop it.
|
||||||
|
*/
|
||||||
|
if (refcnt > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (conn->state) {
|
switch (conn->state) {
|
||||||
|
@ -385,6 +385,16 @@ static const u8 gen_method[5][5] = {
|
|||||||
{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
|
{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io)
|
||||||
|
{
|
||||||
|
/* If either side has unknown io_caps, use JUST WORKS */
|
||||||
|
if (local_io > SMP_IO_KEYBOARD_DISPLAY ||
|
||||||
|
remote_io > SMP_IO_KEYBOARD_DISPLAY)
|
||||||
|
return JUST_WORKS;
|
||||||
|
|
||||||
|
return gen_method[remote_io][local_io];
|
||||||
|
}
|
||||||
|
|
||||||
static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
||||||
u8 local_io, u8 remote_io)
|
u8 local_io, u8 remote_io)
|
||||||
{
|
{
|
||||||
@ -401,14 +411,11 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
|||||||
BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
|
BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
|
||||||
|
|
||||||
/* If neither side wants MITM, use JUST WORKS */
|
/* If neither side wants MITM, use JUST WORKS */
|
||||||
/* If either side has unknown io_caps, use JUST WORKS */
|
|
||||||
/* Otherwise, look up method from the table */
|
/* Otherwise, look up method from the table */
|
||||||
if (!(auth & SMP_AUTH_MITM) ||
|
if (!(auth & SMP_AUTH_MITM))
|
||||||
local_io > SMP_IO_KEYBOARD_DISPLAY ||
|
|
||||||
remote_io > SMP_IO_KEYBOARD_DISPLAY)
|
|
||||||
method = JUST_WORKS;
|
method = JUST_WORKS;
|
||||||
else
|
else
|
||||||
method = gen_method[remote_io][local_io];
|
method = get_auth_method(smp, local_io, remote_io);
|
||||||
|
|
||||||
/* If not bonding, don't ask user to confirm a Zero TK */
|
/* If not bonding, don't ask user to confirm a Zero TK */
|
||||||
if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
|
if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
|
||||||
@ -669,7 +676,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||||||
{
|
{
|
||||||
struct smp_cmd_pairing rsp, *req = (void *) skb->data;
|
struct smp_cmd_pairing rsp, *req = (void *) skb->data;
|
||||||
struct smp_chan *smp;
|
struct smp_chan *smp;
|
||||||
u8 key_size, auth;
|
u8 key_size, auth, sec_level;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
BT_DBG("conn %p", conn);
|
BT_DBG("conn %p", conn);
|
||||||
@ -695,7 +702,19 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||||||
/* We didn't start the pairing, so match remote */
|
/* We didn't start the pairing, so match remote */
|
||||||
auth = req->auth_req;
|
auth = req->auth_req;
|
||||||
|
|
||||||
conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
|
sec_level = authreq_to_seclevel(auth);
|
||||||
|
if (sec_level > conn->hcon->pending_sec_level)
|
||||||
|
conn->hcon->pending_sec_level = sec_level;
|
||||||
|
|
||||||
|
/* If we need MITM check that it can be acheived */
|
||||||
|
if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) {
|
||||||
|
u8 method;
|
||||||
|
|
||||||
|
method = get_auth_method(smp, conn->hcon->io_capability,
|
||||||
|
req->io_capability);
|
||||||
|
if (method == JUST_WORKS || method == JUST_CFM)
|
||||||
|
return SMP_AUTH_REQUIREMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
build_pairing_cmd(conn, req, &rsp, auth);
|
build_pairing_cmd(conn, req, &rsp, auth);
|
||||||
|
|
||||||
@ -743,6 +762,16 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||||||
if (check_enc_key_size(conn, key_size))
|
if (check_enc_key_size(conn, key_size))
|
||||||
return SMP_ENC_KEY_SIZE;
|
return SMP_ENC_KEY_SIZE;
|
||||||
|
|
||||||
|
/* If we need MITM check that it can be acheived */
|
||||||
|
if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) {
|
||||||
|
u8 method;
|
||||||
|
|
||||||
|
method = get_auth_method(smp, req->io_capability,
|
||||||
|
rsp->io_capability);
|
||||||
|
if (method == JUST_WORKS || method == JUST_CFM)
|
||||||
|
return SMP_AUTH_REQUIREMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
get_random_bytes(smp->prnd, sizeof(smp->prnd));
|
get_random_bytes(smp->prnd, sizeof(smp->prnd));
|
||||||
|
|
||||||
smp->prsp[0] = SMP_CMD_PAIRING_RSP;
|
smp->prsp[0] = SMP_CMD_PAIRING_RSP;
|
||||||
@ -838,6 +867,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||||||
struct smp_cmd_pairing cp;
|
struct smp_cmd_pairing cp;
|
||||||
struct hci_conn *hcon = conn->hcon;
|
struct hci_conn *hcon = conn->hcon;
|
||||||
struct smp_chan *smp;
|
struct smp_chan *smp;
|
||||||
|
u8 sec_level;
|
||||||
|
|
||||||
BT_DBG("conn %p", conn);
|
BT_DBG("conn %p", conn);
|
||||||
|
|
||||||
@ -847,7 +877,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
|||||||
if (!(conn->hcon->link_mode & HCI_LM_MASTER))
|
if (!(conn->hcon->link_mode & HCI_LM_MASTER))
|
||||||
return SMP_CMD_NOTSUPP;
|
return SMP_CMD_NOTSUPP;
|
||||||
|
|
||||||
hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
|
sec_level = authreq_to_seclevel(rp->auth_req);
|
||||||
|
if (sec_level > hcon->pending_sec_level)
|
||||||
|
hcon->pending_sec_level = sec_level;
|
||||||
|
|
||||||
if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
|
if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
|
||||||
return 0;
|
return 0;
|
||||||
@ -901,9 +933,12 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
|||||||
if (smp_sufficient_security(hcon, sec_level))
|
if (smp_sufficient_security(hcon, sec_level))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (sec_level > hcon->pending_sec_level)
|
||||||
|
hcon->pending_sec_level = sec_level;
|
||||||
|
|
||||||
if (hcon->link_mode & HCI_LM_MASTER)
|
if (hcon->link_mode & HCI_LM_MASTER)
|
||||||
if (smp_ltk_encrypt(conn, sec_level))
|
if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
|
||||||
goto done;
|
return 0;
|
||||||
|
|
||||||
if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
|
if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
|
||||||
return 0;
|
return 0;
|
||||||
@ -918,7 +953,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
|||||||
* requires it.
|
* requires it.
|
||||||
*/
|
*/
|
||||||
if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT ||
|
if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT ||
|
||||||
sec_level > BT_SECURITY_MEDIUM)
|
hcon->pending_sec_level > BT_SECURITY_MEDIUM)
|
||||||
authreq |= SMP_AUTH_MITM;
|
authreq |= SMP_AUTH_MITM;
|
||||||
|
|
||||||
if (hcon->link_mode & HCI_LM_MASTER) {
|
if (hcon->link_mode & HCI_LM_MASTER) {
|
||||||
@ -937,9 +972,6 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
|||||||
|
|
||||||
set_bit(SMP_FLAG_INITIATOR, &smp->flags);
|
set_bit(SMP_FLAG_INITIATOR, &smp->flags);
|
||||||
|
|
||||||
done:
|
|
||||||
hcon->pending_sec_level = sec_level;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user