Bluetooth: Fix balancing of hci_conn refcnts
When LE was added, the refcnt's for the hci_conns used were not balanced
and some of this bleeded over between LE pairing and Legacy pairing.
CRs-fixed: 305391
Signed-off-by: Brian Gix <bgix@codeaurora.org>
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d5477cd..2891209 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3032,6 +3032,7 @@
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
mgmt_connected(hdev->id, &ev->bdaddr);
+ hci_conn_hold(conn);
hci_conn_hold_device(conn);
hci_conn_add_sysfs(conn);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 6ec00d5..354207d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1336,8 +1336,6 @@
conn->security_cfm_cb = NULL;
conn->disconn_cfm_cb = NULL;
- hci_conn_put(conn);
-
mgmt_pending_remove(cmd);
}
@@ -1356,7 +1354,7 @@
pairing_complete(cmd, status);
}
-static void security_complete_cb(struct hci_conn *conn, u8 status)
+static void pairing_security_complete_cb(struct hci_conn *conn, u8 status)
{
struct pending_cmd *cmd;
@@ -1375,7 +1373,7 @@
pairing_complete(cmd, status);
}
-static void connect_complete_cb(struct hci_conn *conn, u8 status)
+static void pairing_connect_complete_cb(struct hci_conn *conn, u8 status)
{
struct pending_cmd *cmd;
@@ -1386,6 +1384,7 @@
BT_DBG("Unable to find a pending command");
return;
}
+ hci_conn_put(conn);
}
static void discovery_terminated(struct pending_cmd *cmd, void *data)
@@ -1465,8 +1464,8 @@
goto unlock;
}
- conn->connect_cfm_cb = connect_complete_cb;
- conn->security_cfm_cb = security_complete_cb;
+ conn->connect_cfm_cb = pairing_connect_complete_cb;
+ conn->security_cfm_cb = pairing_security_complete_cb;
conn->disconn_cfm_cb = pairing_complete_cb;
conn->io_capability = io_cap;
cmd->user_data = conn;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 4b25081..8b2a92e 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -394,17 +394,17 @@
return 0;
}
-int le_user_confirm_reply(struct hci_conn *hdev, u16 mgmt_op, void *cp)
+int le_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, void *cp)
{
struct mgmt_cp_user_passkey_reply *psk_reply = cp;
- struct l2cap_conn *conn = hdev->smp_conn;
+ struct l2cap_conn *conn = hcon->smp_conn;
u8 key[16];
u8 reason = 0;
int ret = 0;
BT_DBG("");
- hdev->tk_valid = TRUE;
+ hcon->tk_valid = TRUE;
switch (mgmt_op) {
case MGMT_OP_USER_CONFIRM_NEG_REPLY:
@@ -416,7 +416,7 @@
memset(key, 0, sizeof(key));
BT_DBG("PassKey: %d", psk_reply->passkey);
put_unaligned_le32(psk_reply->passkey, key);
- swap128(key, hdev->tk);
+ swap128(key, hcon->tk);
break;
default:
reason = SMP_CONFIRM_FAILED;
@@ -428,7 +428,8 @@
BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL");
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
&reason);
- } else if (hdev->cfm_pending) {
+ hci_conn_put(hcon);
+ } else if (hcon->cfm_pending) {
BT_DBG("send_pairing_confirm");
ret = send_pairing_confirm(conn);
}
@@ -836,6 +837,7 @@
case SMP_CMD_PAIRING_FAIL:
reason = 0;
err = -EPERM;
+ hci_conn_put(hcon);
break;
case SMP_CMD_PAIRING_RSP:
@@ -882,6 +884,7 @@
BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
&reason);
+ hci_conn_put(hcon);
}
kfree_skb(skb);
@@ -969,8 +972,10 @@
*keydist &= ~SMP_DIST_SIGN;
}
- if (hcon->out || rsp->resp_key_dist)
+ if (hcon->out || rsp->resp_key_dist) {
hcon->disconn_cfm_cb(hcon, 0);
+ hci_conn_put(hcon);
+ }
return 0;
}