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
Родитель d949cfedbc cb28c306b9
Коммит 92d7c74b6f
3 изменённых файлов: 29 добавлений и 10 удалений

Просмотреть файл

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

Просмотреть файл

@ -2422,30 +2422,51 @@ unlock:
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 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)
return;
goto done;
chan = conn->smp;
if (!chan)
return;
goto done;
l2cap_chan_lock(chan);
smp = chan->data;
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))
smp_failure(conn, 0);
else
smp_failure(conn, SMP_UNSPECIFIED);
err = 0;
}
l2cap_chan_unlock(chan);
done:
return err;
}
static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)

Просмотреть файл

@ -181,7 +181,8 @@ enum smp_key_pref {
};
/* 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,
enum smp_key_pref key_pref);
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);