@@ -1068,6 +1068,17 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
1068
1068
return conn ;
1069
1069
}
1070
1070
1071
+ static bool hci_conn_unlink (struct hci_conn * conn )
1072
+ {
1073
+ if (!conn -> link )
1074
+ return false;
1075
+
1076
+ conn -> link -> link = NULL ;
1077
+ conn -> link = NULL ;
1078
+
1079
+ return true;
1080
+ }
1081
+
1071
1082
int hci_conn_del (struct hci_conn * conn )
1072
1083
{
1073
1084
struct hci_dev * hdev = conn -> hdev ;
@@ -1079,15 +1090,16 @@ int hci_conn_del(struct hci_conn *conn)
1079
1090
cancel_delayed_work_sync (& conn -> idle_work );
1080
1091
1081
1092
if (conn -> type == ACL_LINK ) {
1082
- struct hci_conn * sco = conn -> link ;
1083
- if (sco ) {
1084
- sco -> link = NULL ;
1093
+ struct hci_conn * link = conn -> link ;
1094
+
1095
+ if (link ) {
1096
+ hci_conn_unlink (conn );
1085
1097
/* Due to race, SCO connection might be not established
1086
1098
* yet at this point. Delete it now, otherwise it is
1087
1099
* possible for it to be stuck and can't be deleted.
1088
1100
*/
1089
- if (sco -> handle == HCI_CONN_HANDLE_UNSET )
1090
- hci_conn_del (sco );
1101
+ if (link -> handle == HCI_CONN_HANDLE_UNSET )
1102
+ hci_conn_del (link );
1091
1103
}
1092
1104
1093
1105
/* Unacked frames */
@@ -1103,7 +1115,7 @@ int hci_conn_del(struct hci_conn *conn)
1103
1115
struct hci_conn * acl = conn -> link ;
1104
1116
1105
1117
if (acl ) {
1106
- acl -> link = NULL ;
1118
+ hci_conn_unlink ( conn ) ;
1107
1119
hci_conn_drop (acl );
1108
1120
}
1109
1121
@@ -2434,6 +2446,12 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
2434
2446
c -> state = BT_CLOSED ;
2435
2447
2436
2448
hci_disconn_cfm (c , HCI_ERROR_LOCAL_HOST_TERM );
2449
+
2450
+ /* Unlink before deleting otherwise it is possible that
2451
+ * hci_conn_del removes the link which may cause the list to
2452
+ * contain items already freed.
2453
+ */
2454
+ hci_conn_unlink (c );
2437
2455
hci_conn_del (c );
2438
2456
}
2439
2457
}
0 commit comments