mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02: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:
parent
5761d003da
commit
2f5d635ad5
|
|
@ -7152,12 +7152,23 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
|
||||||
return err;
|
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 hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync, conn,
|
err = hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync,
|
||||||
NULL);
|
hci_conn_get(conn),
|
||||||
|
hci_acl_create_conn_sync_complete);
|
||||||
|
if (err)
|
||||||
|
hci_conn_put(conn);
|
||||||
return (err == -EEXIST) ? 0 : err;
|
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);
|
bt_dev_dbg(hdev, "err %d", err);
|
||||||
|
|
||||||
if (err == -ECANCELED)
|
if (err == -ECANCELED)
|
||||||
return;
|
goto done;
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
if (!hci_conn_valid(hdev, conn))
|
if (!hci_conn_valid(hdev, conn))
|
||||||
goto done;
|
goto unlock;
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
hci_connect_le_scan_cleanup(conn, 0x00);
|
hci_connect_le_scan_cleanup(conn, 0x00);
|
||||||
goto done;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if connection is still pending */
|
/* Check if connection is still pending */
|
||||||
if (conn != hci_lookup_le_connect(hdev))
|
if (conn != hci_lookup_le_connect(hdev))
|
||||||
goto done;
|
goto unlock;
|
||||||
|
|
||||||
/* Flush to make sure we send create conn cancel command if needed */
|
/* Flush to make sure we send create conn cancel command if needed */
|
||||||
flush_delayed_work(&conn->le_conn_timeout);
|
flush_delayed_work(&conn->le_conn_timeout);
|
||||||
hci_conn_failed(conn, bt_status(err));
|
hci_conn_failed(conn, bt_status(err));
|
||||||
|
|
||||||
done:
|
unlock:
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
|
done:
|
||||||
|
hci_conn_put(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn)
|
int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn)
|
||||||
{
|
{
|
||||||
int err;
|
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);
|
create_le_conn_complete);
|
||||||
|
if (err)
|
||||||
|
hci_conn_put(conn);
|
||||||
return (err == -EEXIST) ? 0 : err;
|
return (err == -EEXIST) ? 0 : err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user