]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Bluetooth: hci_conn: Fix not cleaning up on LE Connection failure
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 24 Mar 2023 17:57:55 +0000 (10:57 -0700)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 10 Apr 2023 17:21:33 +0000 (10:21 -0700)
hci_connect_le_scan_cleanup shall always be invoked to cleanup the
states and re-enable passive scanning if necessary, otherwise it may
cause the pending action to stay active causing multiple attempts to
connect.

Fixes: 9b3628d79b46 ("Bluetooth: hci_sync: Cleanup hci_conn if it cannot be aborted")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/hci_conn.c

index 17b946f9ba317c7c04222379f95b12e104f88a87..5af3f6b011c9509977adb4ba02c4c7a37fb0ef31 100644 (file)
@@ -68,7 +68,7 @@ static const struct sco_param esco_param_msbc[] = {
 };
 
 /* This function requires the caller holds hdev->lock */
-static void hci_connect_le_scan_cleanup(struct hci_conn *conn)
+static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
 {
        struct hci_conn_params *params;
        struct hci_dev *hdev = conn->hdev;
@@ -88,9 +88,28 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn)
 
        params = hci_pend_le_action_lookup(&hdev->pend_le_conns, bdaddr,
                                           bdaddr_type);
-       if (!params || !params->explicit_connect)
+       if (!params)
                return;
 
+       if (params->conn) {
+               hci_conn_drop(params->conn);
+               hci_conn_put(params->conn);
+               params->conn = NULL;
+       }
+
+       if (!params->explicit_connect)
+               return;
+
+       /* If the status indicates successful cancellation of
+        * the attempt (i.e. Unknown Connection Id) there's no point of
+        * notifying failure since we'll go back to keep trying to
+        * connect. The only exception is explicit connect requests
+        * where a timeout + cancel does indicate an actual failure.
+        */
+       if (status && status != HCI_ERROR_UNKNOWN_CONN_ID)
+               mgmt_connect_failed(hdev, &conn->dst, conn->type,
+                                   conn->dst_type, status);
+
        /* The connection attempt was doing scan for new RPA, and is
         * in scan phase. If params are not associated with any other
         * autoconnect action, remove them completely. If they are, just unmark
@@ -178,7 +197,7 @@ static void le_scan_cleanup(struct work_struct *work)
        rcu_read_unlock();
 
        if (c == conn) {
-               hci_connect_le_scan_cleanup(conn);
+               hci_connect_le_scan_cleanup(conn, 0x00);
                hci_conn_cleanup(conn);
        }
 
@@ -1179,31 +1198,8 @@ EXPORT_SYMBOL(hci_get_route);
 static void hci_le_conn_failed(struct hci_conn *conn, u8 status)
 {
        struct hci_dev *hdev = conn->hdev;
-       struct hci_conn_params *params;
 
-       params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
-                                          conn->dst_type);
-       if (params && params->conn) {
-               hci_conn_drop(params->conn);
-               hci_conn_put(params->conn);
-               params->conn = NULL;
-       }
-
-       /* If the status indicates successful cancellation of
-        * the attempt (i.e. Unknown Connection Id) there's no point of
-        * notifying failure since we'll go back to keep trying to
-        * connect. The only exception is explicit connect requests
-        * where a timeout + cancel does indicate an actual failure.
-        */
-       if (status != HCI_ERROR_UNKNOWN_CONN_ID ||
-           (params && params->explicit_connect))
-               mgmt_connect_failed(hdev, &conn->dst, conn->type,
-                                   conn->dst_type, status);
-
-       /* Since we may have temporarily stopped the background scanning in
-        * favor of connection establishment, we should restart it.
-        */
-       hci_update_passive_scan(hdev);
+       hci_connect_le_scan_cleanup(conn, status);
 
        /* Enable advertising in case this was a failed connection
         * attempt as a peripheral.
@@ -1240,7 +1236,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
        hci_dev_lock(hdev);
 
        if (!err) {
-               hci_connect_le_scan_cleanup(conn);
+               hci_connect_le_scan_cleanup(conn, 0x00);
                goto done;
        }