Context |
Check |
Description |
tedd_an/pre-ci_am |
success
|
Success
|
tedd_an/CheckPatch |
success
|
CheckPatch PASS
|
tedd_an/GitLint |
success
|
Gitlint PASS
|
tedd_an/SubjectPrefix |
success
|
Gitlint PASS
|
tedd_an/BuildKernel |
success
|
BuildKernel PASS
|
tedd_an/CheckAllWarning |
success
|
CheckAllWarning PASS
|
tedd_an/CheckSparse |
success
|
CheckSparse PASS
|
tedd_an/CheckSmatch |
success
|
CheckSparse PASS
|
tedd_an/BuildKernel32 |
success
|
BuildKernel32 PASS
|
tedd_an/TestRunnerSetup |
success
|
TestRunnerSetup PASS
|
tedd_an/TestRunner_l2cap-tester |
success
|
TestRunner PASS
|
tedd_an/TestRunner_iso-tester |
success
|
TestRunner PASS
|
tedd_an/TestRunner_bnep-tester |
success
|
TestRunner PASS
|
tedd_an/TestRunner_mgmt-tester |
success
|
TestRunner PASS
|
tedd_an/TestRunner_rfcomm-tester |
success
|
TestRunner PASS
|
tedd_an/TestRunner_sco-tester |
success
|
TestRunner PASS
|
tedd_an/TestRunner_ioctl-tester |
success
|
TestRunner PASS
|
tedd_an/TestRunner_mesh-tester |
success
|
TestRunner PASS
|
tedd_an/TestRunner_smp-tester |
success
|
TestRunner PASS
|
tedd_an/TestRunner_userchan-tester |
success
|
TestRunner PASS
|
tedd_an/IncrementalBuild |
success
|
Incremental Build PASS
|
@@ -1069,6 +1069,17 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
return conn;
}
+static bool hci_conn_unlink(struct hci_conn *conn)
+{
+ if (!conn->link)
+ return false;
+
+ conn->link->link = NULL;
+ conn->link = NULL;
+
+ return true;
+}
+
int hci_conn_del(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
@@ -1080,15 +1091,16 @@ int hci_conn_del(struct hci_conn *conn)
cancel_delayed_work_sync(&conn->idle_work);
if (conn->type == ACL_LINK) {
- struct hci_conn *sco = conn->link;
- if (sco) {
- sco->link = NULL;
+ struct hci_conn *link = conn->link;
+
+ if (link) {
+ hci_conn_unlink(conn);
/* Due to race, SCO connection might be not established
* yet at this point. Delete it now, otherwise it is
* possible for it to be stuck and can't be deleted.
*/
- if (sco->handle == HCI_CONN_HANDLE_UNSET)
- hci_conn_del(sco);
+ if (link->handle == HCI_CONN_HANDLE_UNSET)
+ hci_conn_del(link);
}
/* Unacked frames */
@@ -1104,7 +1116,7 @@ int hci_conn_del(struct hci_conn *conn)
struct hci_conn *acl = conn->link;
if (acl) {
- acl->link = NULL;
+ hci_conn_unlink(conn);
hci_conn_drop(acl);
}
@@ -2444,6 +2456,12 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
c->state = BT_CLOSED;
hci_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
+
+ /* Unlink before deleting otherwise it is possible that
+ * hci_conn_del removes the link which may cause the list to
+ * contain items already freed.
+ */
+ hci_conn_unlink(c);
hci_conn_del(c);
}
}