Commit 85fa3512 authored by Shuvam Pandey's avatar Shuvam Pandey Committed by Luiz Augusto von Dentz
Browse files

Bluetooth: hci_event: fix potential UAF in SSP passkey handlers



hci_conn lookup and field access must be covered by hdev lock in
hci_user_passkey_notify_evt() and hci_keypress_notify_evt(), otherwise
the connection can be freed concurrently.

Extend the hci_dev_lock critical section to cover all conn usage in both
handlers.

Keep the existing keypress notification behavior unchanged by routing
the early exits through a common unlock path.

Fixes: 92a25256 ("Bluetooth: mgmt: Implement support for passkey notification")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarShuvam Pandey <shuvampandey1@gmail.com>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent a0cff16d
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -5495,9 +5495,11 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data,

	bt_dev_dbg(hdev, "");

	hci_dev_lock(hdev);

	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
	if (!conn)
		return;
		goto unlock;

	conn->passkey_notify = __le32_to_cpu(ev->passkey);
	conn->passkey_entered = 0;
@@ -5506,6 +5508,9 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data,
		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
					 conn->dst_type, conn->passkey_notify,
					 conn->passkey_entered);

unlock:
	hci_dev_unlock(hdev);
}

static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data,
@@ -5516,14 +5521,16 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data,

	bt_dev_dbg(hdev, "");

	hci_dev_lock(hdev);

	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
	if (!conn)
		return;
		goto unlock;

	switch (ev->type) {
	case HCI_KEYPRESS_STARTED:
		conn->passkey_entered = 0;
		return;
		goto unlock;

	case HCI_KEYPRESS_ENTERED:
		conn->passkey_entered++;
@@ -5538,13 +5545,16 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data,
		break;

	case HCI_KEYPRESS_COMPLETED:
		return;
		goto unlock;
	}

	if (hci_dev_test_flag(hdev, HCI_MGMT))
		mgmt_user_passkey_notify(hdev, &conn->dst, conn->type,
					 conn->dst_type, conn->passkey_notify,
					 conn->passkey_entered);

unlock:
	hci_dev_unlock(hdev);
}

static void hci_simple_pair_complete_evt(struct hci_dev *hdev, void *data,