Bluetooth: hci_conn: Always allocate unique handles
This attempts to always allocate a unique handle for connections so they can be properly aborted by the likes of hci_abort_conn, so this uses the invalid range as a pool of unset handles that way if userspace is trying to create multiple connections at once each will be given a unique handle which will be considered unset. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
04a51d6169
commit
9f78191cc9
|
@ -321,8 +321,8 @@ struct adv_monitor {
|
||||||
|
|
||||||
#define HCI_MAX_SHORT_NAME_LENGTH 10
|
#define HCI_MAX_SHORT_NAME_LENGTH 10
|
||||||
|
|
||||||
#define HCI_CONN_HANDLE_UNSET 0xffff
|
|
||||||
#define HCI_CONN_HANDLE_MAX 0x0eff
|
#define HCI_CONN_HANDLE_MAX 0x0eff
|
||||||
|
#define HCI_CONN_HANDLE_UNSET(_handle) (_handle > HCI_CONN_HANDLE_MAX)
|
||||||
|
|
||||||
/* Min encryption key size to match with SMP */
|
/* Min encryption key size to match with SMP */
|
||||||
#define HCI_MIN_ENC_KEY_SIZE 7
|
#define HCI_MIN_ENC_KEY_SIZE 7
|
||||||
|
|
|
@ -932,6 +932,25 @@ static void cis_cleanup(struct hci_conn *conn)
|
||||||
hci_le_remove_cig(hdev, conn->iso_qos.ucast.cig);
|
hci_le_remove_cig(hdev, conn->iso_qos.ucast.cig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u16 hci_conn_hash_alloc_unset(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct hci_conn_hash *h = &hdev->conn_hash;
|
||||||
|
struct hci_conn *c;
|
||||||
|
u16 handle = HCI_CONN_HANDLE_MAX + 1;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
list_for_each_entry_rcu(c, &h->list, list) {
|
||||||
|
/* Find the first unused handle */
|
||||||
|
if (handle == 0xffff || c->handle != handle)
|
||||||
|
break;
|
||||||
|
handle++;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||||
u8 role)
|
u8 role)
|
||||||
{
|
{
|
||||||
|
@ -945,7 +964,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||||
|
|
||||||
bacpy(&conn->dst, dst);
|
bacpy(&conn->dst, dst);
|
||||||
bacpy(&conn->src, &hdev->bdaddr);
|
bacpy(&conn->src, &hdev->bdaddr);
|
||||||
conn->handle = HCI_CONN_HANDLE_UNSET;
|
conn->handle = hci_conn_hash_alloc_unset(hdev);
|
||||||
conn->hdev = hdev;
|
conn->hdev = hdev;
|
||||||
conn->type = type;
|
conn->type = type;
|
||||||
conn->role = role;
|
conn->role = role;
|
||||||
|
@ -1057,7 +1076,7 @@ static void hci_conn_unlink(struct hci_conn *conn)
|
||||||
*/
|
*/
|
||||||
if ((child->type == SCO_LINK ||
|
if ((child->type == SCO_LINK ||
|
||||||
child->type == ESCO_LINK) &&
|
child->type == ESCO_LINK) &&
|
||||||
child->handle == HCI_CONN_HANDLE_UNSET)
|
HCI_CONN_HANDLE_UNSET(child->handle))
|
||||||
hci_conn_del(child);
|
hci_conn_del(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1943,7 +1962,7 @@ int hci_conn_check_create_cis(struct hci_conn *conn)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!conn->parent || conn->parent->state != BT_CONNECTED ||
|
if (!conn->parent || conn->parent->state != BT_CONNECTED ||
|
||||||
conn->state != BT_CONNECT || conn->handle == HCI_CONN_HANDLE_UNSET)
|
conn->state != BT_CONNECT || HCI_CONN_HANDLE_UNSET(conn->handle))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -3173,7 +3173,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
|
||||||
* As the connection handle is set here for the first time, it indicates
|
* As the connection handle is set here for the first time, it indicates
|
||||||
* whether the connection is already set up.
|
* whether the connection is already set up.
|
||||||
*/
|
*/
|
||||||
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
|
if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
|
||||||
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
|
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
@ -5032,7 +5032,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
|
||||||
* As the connection handle is set here for the first time, it indicates
|
* As the connection handle is set here for the first time, it indicates
|
||||||
* whether the connection is already set up.
|
* whether the connection is already set up.
|
||||||
*/
|
*/
|
||||||
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
|
if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
|
||||||
bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete event for existing connection");
|
bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete event for existing connection");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
@ -5896,7 +5896,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
||||||
* As the connection handle is set here for the first time, it indicates
|
* As the connection handle is set here for the first time, it indicates
|
||||||
* whether the connection is already set up.
|
* whether the connection is already set up.
|
||||||
*/
|
*/
|
||||||
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
|
if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
|
||||||
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
|
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue