Bluetooth: Fix LE pairing scenarios when initiated remotely
Fix setting of ENCRYPTION_PENDING and Connection refcnt's that could
be out of sync due to remote slave issued security requests.
Change-Id: Ie72abd0648182db0ef60693820139f40ef2e4bf6
Signed-off-by: Brian Gix <bgix@codeaurora.org>
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a6e2aab..6838fd5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -438,6 +438,7 @@
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
&reason);
del_timer(&hcon->smp_timer);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
hci_conn_put(hcon);
} else if (hcon->cfm_pending) {
@@ -686,6 +687,8 @@
set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+ hci_conn_hold(hcon);
+
return 0;
}
@@ -846,6 +849,7 @@
reason = 0;
err = -EPERM;
del_timer(&hcon->smp_timer);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[1]);
hci_conn_put(hcon);
break;
@@ -895,6 +899,7 @@
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
&reason);
del_timer(&hcon->smp_timer);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
hci_conn_put(hcon);
}
@@ -989,6 +994,7 @@
hcon->disconn_cfm_cb(hcon, 0);
del_timer(&hcon->smp_timer);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
hci_conn_put(hcon);
}
@@ -1002,6 +1008,8 @@
BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
if (!status && encrypt && !hcon->sec_req)
smp_distribute_keys(conn, 0);
@@ -1009,6 +1017,9 @@
else if (hcon->sec_req && (status || !encrypt))
smp_conn_security(conn, hcon->sec_level);
+ else
+ hci_conn_put(hcon);
+
return 0;
}
@@ -1020,6 +1031,7 @@
BT_DBG("%p", conn);
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
hci_conn_put(conn->hcon);
}