mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync
Dereferencing RCU-protected pointers outside critical sections is
invalid and may lead to UAF.
Take hdev->lock for hci_conn lookup and hci_abort_conn(). Don't use RCU
to ensure the conn is fully initialized at this point.
Fixes: 227a0cdf4a ("Bluetooth: MGMT: Fix not generating command complete for MGMT_OP_DISCONNECT")
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
d5efd6e4b8
commit
16cd664439
|
|
@ -3091,6 +3091,8 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data)
|
|||
struct mgmt_cp_unpair_device *cp = cmd->param;
|
||||
struct hci_conn *conn;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (cp->addr.type == BDADDR_BREDR)
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
|
||||
&cp->addr.bdaddr);
|
||||
|
|
@ -3098,6 +3100,11 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data)
|
|||
conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
|
||||
le_addr_type(cp->addr.type));
|
||||
|
||||
if (conn)
|
||||
hci_conn_get(conn);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
if (!conn)
|
||||
return 0;
|
||||
|
||||
|
|
@ -3105,6 +3112,7 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data)
|
|||
* will clean up the connection no matter the error.
|
||||
*/
|
||||
hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
|
||||
hci_conn_put(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3252,6 +3260,8 @@ static int disconnect_sync(struct hci_dev *hdev, void *data)
|
|||
struct mgmt_cp_disconnect *cp = cmd->param;
|
||||
struct hci_conn *conn;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (cp->addr.type == BDADDR_BREDR)
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
|
||||
&cp->addr.bdaddr);
|
||||
|
|
@ -3259,6 +3269,11 @@ static int disconnect_sync(struct hci_dev *hdev, void *data)
|
|||
conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
|
||||
le_addr_type(cp->addr.type));
|
||||
|
||||
if (conn)
|
||||
hci_conn_get(conn);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
if (!conn)
|
||||
return -ENOTCONN;
|
||||
|
||||
|
|
@ -3266,6 +3281,7 @@ static int disconnect_sync(struct hci_dev *hdev, void *data)
|
|||
* will clean up the connection no matter the error.
|
||||
*/
|
||||
hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
|
||||
hci_conn_put(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user