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:
commit
92d7c74b6f
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue