mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 08:45:18 -04:00
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:
committed by
Luiz Augusto von Dentz
parent
5761d003da
commit
2f5d635ad5
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user