Skip to content

Commit

Permalink
bluetooth: host: add checks for connection types
Browse files Browse the repository at this point in the history
Fail gracefully if an HCI event of one type arrives for a handle of a
different connection type.  The requested types are currently based on
what fields are used, not on the usage context, in order to keep every
correct use so far still working.

A warning is logged if the connection identified by the handle does not
match the requested connection type.

Signed-off-by: Arkadiusz Kozdra <[email protected]>
  • Loading branch information
kozdra committed Jun 27, 2023
1 parent 8042218 commit 1415619
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 33 deletions.
2 changes: 1 addition & 1 deletion subsys/bluetooth/host/adv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2195,7 +2195,7 @@ void bt_hci_le_adv_set_terminated(struct net_buf *buf)
}

if (IS_ENABLED(CONFIG_BT_CONN) && !evt->status) {
struct bt_conn *conn = bt_conn_lookup_handle(conn_handle);
struct bt_conn *conn = bt_conn_lookup_handle(conn_handle, BT_CONN_TYPE_LE);

if (conn) {
if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
Expand Down
4 changes: 2 additions & 2 deletions subsys/bluetooth/host/br.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ void bt_hci_read_remote_features_complete(struct net_buf *buf)

LOG_DBG("status 0x%02x handle %u", evt->status, handle);

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_BR);
if (!conn) {
LOG_ERR("Can't find conn for handle %u", handle);
return;
Expand Down Expand Up @@ -666,7 +666,7 @@ void bt_hci_read_remote_ext_features_complete(struct net_buf *buf)

LOG_DBG("status 0x%02x handle %u", evt->status, handle);

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_BR);
if (!conn) {
LOG_ERR("Can't find conn for handle %u", handle);
return;
Expand Down
24 changes: 17 additions & 7 deletions subsys/bluetooth/host/conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1079,8 +1079,10 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
conn->role == BT_CONN_ROLE_PERIPHERAL) {

#if defined(CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS)
conn->le.conn_param_retry_countdown =
CONFIG_BT_CONN_PARAM_RETRY_COUNT;
if (conn->type == BT_CONN_TYPE_LE) {
conn->le.conn_param_retry_countdown =
CONFIG_BT_CONN_PARAM_RETRY_COUNT;
}
#endif /* CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS */

k_work_schedule(&conn->deferred_work,
Expand Down Expand Up @@ -1205,31 +1207,39 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
}
}

struct bt_conn *bt_conn_lookup_handle(uint16_t handle)
struct bt_conn *bt_conn_lookup_handle(uint16_t handle, int type)
{
struct bt_conn *conn;

#if defined(CONFIG_BT_CONN)
conn = conn_lookup_handle(acl_conns, ARRAY_SIZE(acl_conns), handle);
if (conn) {
return conn;
goto found;
}
#endif /* CONFIG_BT_CONN */

#if defined(CONFIG_BT_ISO)
conn = conn_lookup_handle(iso_conns, ARRAY_SIZE(iso_conns), handle);
if (conn) {
return conn;
goto found;
}
#endif

#if defined(CONFIG_BT_BREDR)
#if defined(CONFIG_BT_BREDR)
conn = conn_lookup_handle(sco_conns, ARRAY_SIZE(sco_conns), handle);
if (conn) {
return conn;
goto found;
}
#endif

found:
if (conn) {
if (type & conn->type) {
return conn;
}
LOG_WRN("incompatible handle %u", handle);
bt_conn_unref(conn);
}
return NULL;
}

Expand Down
2 changes: 1 addition & 1 deletion subsys/bluetooth/host/conn_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ void bt_conn_disconnect_all(uint8_t id);
struct bt_conn *bt_conn_new(struct bt_conn *conns, size_t size);

/* Look up an existing connection */
struct bt_conn *bt_conn_lookup_handle(uint16_t handle);
struct bt_conn *bt_conn_lookup_handle(uint16_t handle, int type);

static inline bool bt_conn_is_handle_valid(struct bt_conn *conn)
{
Expand Down
6 changes: 3 additions & 3 deletions subsys/bluetooth/host/direction.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ int hci_df_prepare_connection_iq_report(struct net_buf *buf,

evt = net_buf_pull_mem(buf, sizeof(*evt));

conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle));
conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle), BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unknown conn handle 0x%04X for iq samples report",
sys_le16_to_cpu(evt->conn_handle));
Expand Down Expand Up @@ -732,7 +732,7 @@ int hci_df_vs_prepare_connection_iq_report(struct net_buf *buf,

evt = net_buf_pull_mem(buf, sizeof(*evt));

conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle));
conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle), BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unknown conn handle 0x%04X for iq samples report",
sys_le16_to_cpu(evt->conn_handle));
Expand Down Expand Up @@ -857,7 +857,7 @@ int hci_df_prepare_conn_cte_req_failed(struct net_buf *buf,

evt = net_buf_pull_mem(buf, sizeof(*evt));

conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle));
conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle), BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unknown conn handle 0x%04X for iq samples report",
sys_le16_to_cpu(evt->conn_handle));
Expand Down
26 changes: 13 additions & 13 deletions subsys/bluetooth/host/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ static void hci_num_completed_packets(struct net_buf *buf)

LOG_DBG("handle %u count %u", handle, count);

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_ALL);
if (!conn) {
LOG_ERR("No connection for handle %u", handle);
continue;
Expand Down Expand Up @@ -520,7 +520,7 @@ static void hci_acl(struct net_buf *buf)
return;
}

conn = bt_conn_lookup_handle(acl(buf)->handle);
conn = bt_conn_lookup_handle(acl(buf)->handle, BT_CONN_TYPE_ALL);
if (!conn) {
LOG_ERR("Unable to find conn for handle %u", acl(buf)->handle);
net_buf_unref(buf);
Expand Down Expand Up @@ -824,7 +824,7 @@ static void hci_disconn_complete_prio(struct net_buf *buf)
return;
}

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_ALL);
if (!conn) {
/* Priority disconnect complete event received before normal
* connection complete event.
Expand All @@ -849,7 +849,7 @@ static void hci_disconn_complete(struct net_buf *buf)
return;
}

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_ALL);
if (!conn) {
LOG_ERR("Unable to look up conn with handle %u", handle);
return;
Expand Down Expand Up @@ -1617,7 +1617,7 @@ static void le_remote_feat_complete(struct net_buf *buf)
uint16_t handle = sys_le16_to_cpu(evt->handle);
struct bt_conn *conn;

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unable to lookup conn for handle %u", handle);
return;
Expand Down Expand Up @@ -1645,7 +1645,7 @@ static void le_data_len_change(struct net_buf *buf)
uint16_t handle = sys_le16_to_cpu(evt->handle);
struct bt_conn *conn;

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unable to lookup conn for handle %u", handle);
return;
Expand Down Expand Up @@ -1678,7 +1678,7 @@ static void le_phy_update_complete(struct net_buf *buf)
uint16_t handle = sys_le16_to_cpu(evt->handle);
struct bt_conn *conn;

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unable to lookup conn for handle %u", handle);
return;
Expand Down Expand Up @@ -1774,7 +1774,7 @@ static void le_conn_param_req(struct net_buf *buf)
param.latency = sys_le16_to_cpu(evt->latency);
param.timeout = sys_le16_to_cpu(evt->timeout);

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unable to lookup conn for handle %u", handle);
le_conn_param_neg_reply(handle, BT_HCI_ERR_UNKNOWN_CONN_ID);
Expand All @@ -1800,7 +1800,7 @@ static void le_conn_update_complete(struct net_buf *buf)

LOG_DBG("status 0x%02x, handle %u", evt->status, handle);

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unable to lookup conn for handle %u", handle);
return;
Expand Down Expand Up @@ -2020,7 +2020,7 @@ static void hci_encrypt_change(struct net_buf *buf)

LOG_DBG("status 0x%02x handle %u encrypt 0x%02x", evt->status, handle, evt->encrypt);

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_ALL);
if (!conn) {
LOG_ERR("Unable to look up conn with handle %u", handle);
return;
Expand Down Expand Up @@ -2095,7 +2095,7 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf)

LOG_DBG("status 0x%02x handle %u", evt->status, handle);

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_ALL);
if (!conn) {
LOG_ERR("Unable to look up conn with handle %u", handle);
return;
Expand Down Expand Up @@ -2151,7 +2151,7 @@ static void bt_hci_evt_read_remote_version_complete(struct net_buf *buf)

evt = net_buf_pull_mem(buf, sizeof(*evt));
handle = sys_le16_to_cpu(evt->handle);
conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_ALL);
if (!conn) {
LOG_ERR("No connection for handle %u", handle);
return;
Expand Down Expand Up @@ -2232,7 +2232,7 @@ static void le_ltk_request(struct net_buf *buf)

LOG_DBG("handle %u", handle);

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unable to lookup conn for handle %u", handle);
return;
Expand Down
8 changes: 4 additions & 4 deletions subsys/bluetooth/host/iso.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ void hci_iso(struct net_buf *buf)
return;
}

iso = bt_conn_lookup_handle(iso(buf)->handle);
iso = bt_conn_lookup_handle(iso(buf)->handle, BT_CONN_TYPE_ISO);
if (iso == NULL) {
LOG_ERR("Unable to find conn for handle %u", iso(buf)->handle);
net_buf_unref(buf);
Expand Down Expand Up @@ -982,7 +982,7 @@ void hci_le_cis_established(struct net_buf *buf)
LOG_DBG("status 0x%02x handle %u", evt->status, handle);

/* ISO connection handles are already assigned at this point */
iso = bt_conn_lookup_handle(handle);
iso = bt_conn_lookup_handle(handle, BT_CONN_TYPE_ISO);
if (!iso) {
LOG_ERR("No connection found for handle %u", handle);
return;
Expand Down Expand Up @@ -1229,7 +1229,7 @@ void hci_le_cis_req(struct net_buf *buf)
}

/* Lookup existing connection with same handle */
iso = bt_conn_lookup_handle(cis_handle);
iso = bt_conn_lookup_handle(cis_handle, BT_CONN_TYPE_ISO);
if (iso) {
LOG_ERR("Invalid ISO handle %u", cis_handle);
hci_le_reject_cis(cis_handle, BT_HCI_ERR_CONN_LIMIT_EXCEEDED);
Expand All @@ -1238,7 +1238,7 @@ void hci_le_cis_req(struct net_buf *buf)
}

/* Lookup ACL connection to attach */
acl = bt_conn_lookup_handle(acl_handle);
acl = bt_conn_lookup_handle(acl_handle, BT_CONN_TYPE_LE);
if (!acl) {
LOG_ERR("Invalid ACL handle %u", acl_handle);
hci_le_reject_cis(cis_handle, BT_HCI_ERR_UNKNOWN_CONN_ID);
Expand Down
3 changes: 2 additions & 1 deletion subsys/bluetooth/host/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,8 @@ static void bt_hci_le_past_received_common(struct net_buf *buf)
}

sync_info.conn = bt_conn_lookup_handle(
sys_le16_to_cpu(evt->conn_handle));
sys_le16_to_cpu(evt->conn_handle),
BT_CONN_TYPE_LE);

if (!sync_info.conn) {
LOG_ERR("Could not lookup connection handle from PAST");
Expand Down
2 changes: 1 addition & 1 deletion subsys/bluetooth/host/ssp.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ void bt_hci_auth_complete(struct net_buf *buf)

LOG_DBG("status 0x%02x, handle %u", evt->status, handle);

conn = bt_conn_lookup_handle(handle);
conn = bt_conn_lookup_handle(handle, BT_CONN_TYPE_BR);
if (!conn) {
LOG_ERR("Can't find conn for handle %u", handle);
return;
Expand Down

0 comments on commit 1415619

Please sign in to comment.