Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92d7c74b authored by David S. Miller's avatar David S. Miller
Browse files


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: default avatarDavid S. Miller <davem@davemloft.net>
parents d949cfed cb28c306
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -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.
+25 −4
Original line number Diff line number Diff line
@@ -2422,30 +2422,51 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
	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)
+2 −1
Original line number Diff line number Diff line
@@ -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);