Skip to content

Commit 9f78191

Browse files
committed
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 <[email protected]>
1 parent 04a51d6 commit 9f78191

File tree

3 files changed

+26
-7
lines changed

3 files changed

+26
-7
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,8 @@ struct adv_monitor {
321321

322322
#define HCI_MAX_SHORT_NAME_LENGTH 10
323323

324-
#define HCI_CONN_HANDLE_UNSET 0xffff
325324
#define HCI_CONN_HANDLE_MAX 0x0eff
325+
#define HCI_CONN_HANDLE_UNSET(_handle) (_handle > HCI_CONN_HANDLE_MAX)
326326

327327
/* Min encryption key size to match with SMP */
328328
#define HCI_MIN_ENC_KEY_SIZE 7

net/bluetooth/hci_conn.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,25 @@ static void cis_cleanup(struct hci_conn *conn)
932932
hci_le_remove_cig(hdev, conn->iso_qos.ucast.cig);
933933
}
934934

935+
static u16 hci_conn_hash_alloc_unset(struct hci_dev *hdev)
936+
{
937+
struct hci_conn_hash *h = &hdev->conn_hash;
938+
struct hci_conn *c;
939+
u16 handle = HCI_CONN_HANDLE_MAX + 1;
940+
941+
rcu_read_lock();
942+
943+
list_for_each_entry_rcu(c, &h->list, list) {
944+
/* Find the first unused handle */
945+
if (handle == 0xffff || c->handle != handle)
946+
break;
947+
handle++;
948+
}
949+
rcu_read_unlock();
950+
951+
return handle;
952+
}
953+
935954
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
936955
u8 role)
937956
{
@@ -945,7 +964,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
945964

946965
bacpy(&conn->dst, dst);
947966
bacpy(&conn->src, &hdev->bdaddr);
948-
conn->handle = HCI_CONN_HANDLE_UNSET;
967+
conn->handle = hci_conn_hash_alloc_unset(hdev);
949968
conn->hdev = hdev;
950969
conn->type = type;
951970
conn->role = role;
@@ -1057,7 +1076,7 @@ static void hci_conn_unlink(struct hci_conn *conn)
10571076
*/
10581077
if ((child->type == SCO_LINK ||
10591078
child->type == ESCO_LINK) &&
1060-
child->handle == HCI_CONN_HANDLE_UNSET)
1079+
HCI_CONN_HANDLE_UNSET(child->handle))
10611080
hci_conn_del(child);
10621081
}
10631082

@@ -1943,7 +1962,7 @@ int hci_conn_check_create_cis(struct hci_conn *conn)
19431962
return -EINVAL;
19441963

19451964
if (!conn->parent || conn->parent->state != BT_CONNECTED ||
1946-
conn->state != BT_CONNECT || conn->handle == HCI_CONN_HANDLE_UNSET)
1965+
conn->state != BT_CONNECT || HCI_CONN_HANDLE_UNSET(conn->handle))
19471966
return 1;
19481967

19491968
return 0;

net/bluetooth/hci_event.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3173,7 +3173,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
31733173
* As the connection handle is set here for the first time, it indicates
31743174
* whether the connection is already set up.
31753175
*/
3176-
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
3176+
if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
31773177
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
31783178
goto unlock;
31793179
}
@@ -5032,7 +5032,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
50325032
* As the connection handle is set here for the first time, it indicates
50335033
* whether the connection is already set up.
50345034
*/
5035-
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
5035+
if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
50365036
bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete event for existing connection");
50375037
goto unlock;
50385038
}
@@ -5896,7 +5896,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
58965896
* As the connection handle is set here for the first time, it indicates
58975897
* whether the connection is already set up.
58985898
*/
5899-
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
5899+
if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
59005900
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
59015901
goto unlock;
59025902
}

0 commit comments

Comments
 (0)