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

Johan Hedberg says:

====================
pull request: bluetooth 2018-09-27

Here's one more Bluetooth fix for 4.19, fixing the handling of an
attempt to unpair a device while pairing is in progress.

Let me know if there are any issues pulling. Thanks.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2018-10-01 22:40:39 -07:00
commit 92d7c74b6f
3 changed files with 29 additions and 10 deletions

View File

@ -2434,9 +2434,8 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
/* LE address type */ /* LE address type */
addr_type = le_addr_type(cp->addr.type); addr_type = le_addr_type(cp->addr.type);
hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type); /* Abort any ongoing SMP pairing. Removes ltk and irk if they exist. */
err = smp_cancel_and_remove_pairing(hdev, &cp->addr.bdaddr, addr_type);
err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
if (err < 0) { if (err < 0) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_NOT_PAIRED, &rp, MGMT_STATUS_NOT_PAIRED, &rp,
@ -2450,8 +2449,6 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
goto done; goto done;
} }
/* Abort any ongoing SMP pairing */
smp_cancel_pairing(conn);
/* Defer clearing up the connection parameters until closing to /* Defer clearing up the connection parameters until closing to
* give a chance of keeping them if a repairing happens. * give a chance of keeping them if a repairing happens.

View File

@ -2422,30 +2422,51 @@ unlock:
return ret; return ret;
} }
void smp_cancel_pairing(struct hci_conn *hcon) int smp_cancel_and_remove_pairing(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type)
{ {
struct l2cap_conn *conn = hcon->l2cap_data; struct hci_conn *hcon;
struct l2cap_conn *conn;
struct l2cap_chan *chan; struct l2cap_chan *chan;
struct smp_chan *smp; struct smp_chan *smp;
int err;
err = hci_remove_ltk(hdev, bdaddr, addr_type);
hci_remove_irk(hdev, bdaddr, addr_type);
hcon = hci_conn_hash_lookup_le(hdev, bdaddr, addr_type);
if (!hcon)
goto done;
conn = hcon->l2cap_data;
if (!conn) if (!conn)
return; goto done;
chan = conn->smp; chan = conn->smp;
if (!chan) if (!chan)
return; goto done;
l2cap_chan_lock(chan); l2cap_chan_lock(chan);
smp = chan->data; smp = chan->data;
if (smp) { if (smp) {
/* Set keys to NULL to make sure smp_failure() does not try to
* remove and free already invalidated rcu list entries. */
smp->ltk = NULL;
smp->slave_ltk = NULL;
smp->remote_irk = NULL;
if (test_bit(SMP_FLAG_COMPLETE, &smp->flags)) if (test_bit(SMP_FLAG_COMPLETE, &smp->flags))
smp_failure(conn, 0); smp_failure(conn, 0);
else else
smp_failure(conn, SMP_UNSPECIFIED); smp_failure(conn, SMP_UNSPECIFIED);
err = 0;
} }
l2cap_chan_unlock(chan); l2cap_chan_unlock(chan);
done:
return err;
} }
static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)

View File

@ -181,7 +181,8 @@ enum smp_key_pref {
}; };
/* SMP Commands */ /* SMP Commands */
void smp_cancel_pairing(struct hci_conn *hcon); int smp_cancel_and_remove_pairing(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type);
bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level, bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
enum smp_key_pref key_pref); enum smp_key_pref key_pref);
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);