]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Bluetooth: hci_conn: Fix UAF Write in __hci_acl_create_connection_sync
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 9 Feb 2024 14:08:06 +0000 (09:08 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Sep 2024 09:11:33 +0000 (11:11 +0200)
[ Upstream commit 5f641f03abccddd1a37233ff1b8e774b9ff1f4e8 ]

This fixes the UAF on __hci_acl_create_connection_sync caused by
connection abortion, it uses the same logic as to LE_LINK which uses
hci_cmd_sync_cancel to prevent the callback to run if the connection is
abort prematurely.

Reported-by: syzbot+3f0a39be7a2035700868@syzkaller.appspotmail.com
Fixes: 45340097ce6e ("Bluetooth: hci_conn: Only do ACL connections sequentially")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Stable-dep-of: 227a0cdf4a02 ("Bluetooth: MGMT: Fix not generating command complete for MGMT_OP_DISCONNECT")
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/bluetooth/hci_sync.h
net/bluetooth/hci_conn.c
net/bluetooth/hci_sync.c

index 532230150cc9f106c992f41f498a5e203de6363c..37ca8477b3f47f338c96c6862550cd511d06ab34 100644 (file)
@@ -141,5 +141,4 @@ int hci_le_big_terminate_sync(struct hci_dev *hdev, u8 handle);
 
 int hci_le_pa_terminate_sync(struct hci_dev *hdev, u16 handle);
 
-int hci_acl_create_connection_sync(struct hci_dev *hdev,
-                                  struct hci_conn *conn);
+int hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn);
index 36731d047f160737ec8ed40219f4983f6c320e6a..d15c8ce4b4183d869b5bed596927372fdd4e80bd 100644 (file)
@@ -1650,7 +1650,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
                acl->pending_sec_level = sec_level;
                acl->auth_type = auth_type;
 
-               err = hci_acl_create_connection_sync(hdev, acl);
+               err = hci_connect_acl_sync(hdev, acl);
                if (err) {
                        hci_conn_del(acl);
                        return ERR_PTR(err);
@@ -2913,6 +2913,7 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
         */
        if (conn->state == BT_CONNECT && hdev->req_status == HCI_REQ_PEND) {
                switch (hci_skb_event(hdev->sent_cmd)) {
+               case HCI_EV_CONN_COMPLETE:
                case HCI_EV_LE_CONN_COMPLETE:
                case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
                case HCI_EVT_LE_CIS_ESTABLISHED:
index 165c532fa2a2fc0c89da5312eb5a6742e411b53d..19ceb7ce66bf29efcfa0388f77b4dd4c3eb1a92f 100644 (file)
@@ -6578,13 +6578,18 @@ int hci_update_adv_data(struct hci_dev *hdev, u8 instance)
                                  UINT_PTR(instance), NULL);
 }
 
-static int __hci_acl_create_connection_sync(struct hci_dev *hdev, void *data)
+static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
 {
-       struct hci_conn *conn = data;
+       struct hci_conn *conn;
+       u16 handle = PTR_UINT(data);
        struct inquiry_entry *ie;
        struct hci_cp_create_conn cp;
        int err;
 
+       conn = hci_conn_hash_lookup_handle(hdev, handle);
+       if (!conn)
+               return 0;
+
        /* Many controllers disallow HCI Create Connection while it is doing
         * HCI Inquiry. So we cancel the Inquiry first before issuing HCI Create
         * Connection. This may cause the MGMT discovering state to become false
@@ -6641,9 +6646,8 @@ static int __hci_acl_create_connection_sync(struct hci_dev *hdev, void *data)
        return err;
 }
 
-int hci_acl_create_connection_sync(struct hci_dev *hdev,
-                                  struct hci_conn *conn)
+int hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn)
 {
-       return hci_cmd_sync_queue(hdev, __hci_acl_create_connection_sync,
-                                 conn, NULL);
+       return hci_cmd_sync_queue(hdev, hci_acl_create_conn_sync,
+                                 UINT_PTR(conn->handle), NULL);
 }