Bluetooth: hci_sync: hold conn in hci_connect_acl/le_sync() callbacks

There is theoretical UAF if the conn is freed while the hci_sync task
is running.

Hold refcount to avoid that.

Fixes: 881559af5f ("Bluetooth: hci_sync: Attempt to dequeue connection attempt")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Pauli Virtanen
2026-07-25 12:59:18 +03:00
committed by Luiz Augusto von Dentz
parent 5761d003da
commit 2f5d635ad5

View File

@@ -7152,12 +7152,23 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
return err;
}
static void hci_acl_create_conn_sync_complete(struct hci_dev *hdev, void *data,
int err)
{
struct hci_conn *conn = data;
hci_conn_put(conn);
}
int hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn)
{
int err;
err = hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync, conn,
NULL);
err = hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync,
hci_conn_get(conn),
hci_acl_create_conn_sync_complete);
if (err)
hci_conn_put(conn);
return (err == -EEXIST) ? 0 : err;
}
@@ -7168,36 +7179,41 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
bt_dev_dbg(hdev, "err %d", err);
if (err == -ECANCELED)
return;
goto done;
hci_dev_lock(hdev);
if (!hci_conn_valid(hdev, conn))
goto done;
goto unlock;
if (!err) {
hci_connect_le_scan_cleanup(conn, 0x00);
goto done;
goto unlock;
}
/* Check if connection is still pending */
if (conn != hci_lookup_le_connect(hdev))
goto done;
goto unlock;
/* Flush to make sure we send create conn cancel command if needed */
flush_delayed_work(&conn->le_conn_timeout);
hci_conn_failed(conn, bt_status(err));
done:
unlock:
hci_dev_unlock(hdev);
done:
hci_conn_put(conn);
}
int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn)
{
int err;
err = hci_cmd_sync_queue_once(hdev, hci_le_create_conn_sync, conn,
err = hci_cmd_sync_queue_once(hdev, hci_le_create_conn_sync,
hci_conn_get(conn),
create_le_conn_complete);
if (err)
hci_conn_put(conn);
return (err == -EEXIST) ? 0 : err;
}