@@ -1051,6 +1051,17 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
1051
1051
return conn ;
1052
1052
}
1053
1053
1054
+ static bool hci_conn_unlink (struct hci_conn * conn )
1055
+ {
1056
+ if (!conn -> link )
1057
+ return false;
1058
+
1059
+ conn -> link -> link = NULL ;
1060
+ conn -> link = NULL ;
1061
+
1062
+ return true;
1063
+ }
1064
+
1054
1065
int hci_conn_del (struct hci_conn * conn )
1055
1066
{
1056
1067
struct hci_dev * hdev = conn -> hdev ;
@@ -1062,15 +1073,16 @@ int hci_conn_del(struct hci_conn *conn)
1062
1073
cancel_delayed_work_sync (& conn -> idle_work );
1063
1074
1064
1075
if (conn -> type == ACL_LINK ) {
1065
- struct hci_conn * sco = conn -> link ;
1066
- if (sco ) {
1067
- sco -> link = NULL ;
1076
+ struct hci_conn * link = conn -> link ;
1077
+
1078
+ if (link ) {
1079
+ hci_conn_unlink (conn );
1068
1080
/* Due to race, SCO connection might be not established
1069
1081
* yet at this point. Delete it now, otherwise it is
1070
1082
* possible for it to be stuck and can't be deleted.
1071
1083
*/
1072
- if (sco -> handle == HCI_CONN_HANDLE_UNSET )
1073
- hci_conn_del (sco );
1084
+ if (link -> handle == HCI_CONN_HANDLE_UNSET )
1085
+ hci_conn_del (link );
1074
1086
}
1075
1087
1076
1088
/* Unacked frames */
@@ -1086,7 +1098,7 @@ int hci_conn_del(struct hci_conn *conn)
1086
1098
struct hci_conn * acl = conn -> link ;
1087
1099
1088
1100
if (acl ) {
1089
- acl -> link = NULL ;
1101
+ hci_conn_unlink ( conn ) ;
1090
1102
hci_conn_drop (acl );
1091
1103
}
1092
1104
@@ -2445,6 +2457,12 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
2445
2457
c -> state = BT_CLOSED ;
2446
2458
2447
2459
hci_disconn_cfm (c , HCI_ERROR_LOCAL_HOST_TERM );
2460
+
2461
+ /* Unlink before deleting otherwise it is possible that
2462
+ * hci_conn_del removes the link which may cause the list to
2463
+ * contain items already freed.
2464
+ */
2465
+ hci_conn_unlink (c );
2448
2466
hci_conn_del (c );
2449
2467
}
2450
2468
}
0 commit comments