Merge branch 'idf/ble_iso_sec_fixes_v6.1' into 'release/v6.1'

Idf/ble iso sec fixes (v6.1)

See merge request espressif/esp-idf!50231
This commit is contained in:
Jiang Jiang Jian
2026-07-03 20:30:21 +08:00

View File

@@ -624,6 +624,17 @@ void bt_iso_recv(struct bt_conn *iso, struct net_buf *buf, uint8_t flags)
case BT_ISO_SINGLE:
iso_info.flags = 0;
/* A malformed ISO packet whose ISO_Data_Load_Length is below the SDU
* header size would underflow buf->len in net_buf_pull_mem (the guard
* assert is compiled out in release) and leak OOB bytes into the recv
* callback. Drop it before pulling the header.
*/
if (buf->len < (ts ? sizeof(struct bt_hci_iso_sdu_ts_hdr)
: sizeof(struct bt_hci_iso_sdu_hdr))) {
LOG_ERR("ShortIsoSduHdr[%u][%u]", buf->len, ts);
return;
}
/* The ISO_Data_Load field contains either the first fragment
* of an SDU or a complete SDU.
*/
@@ -1587,10 +1598,27 @@ static bool is_advanced_cig_param(const struct bt_iso_cig_param *param)
return true;
}
/* This probe runs before valid_cig_param(); guard structure here so
* caller misuse (NULL cis_channels/cis/qos, or an over-reported num_cis)
* falls through to that check's -EINVAL instead of a NULL or
* out-of-bounds deref in this probe.
*/
if (param->cis_channels == NULL ||
param->num_cis > BT_ISO_MAX_GROUP_ISO_COUNT ||
param->num_cis > CONFIG_BT_ISO_MAX_CHAN) {
return false;
}
/* Check if any of the CIS contain any test-param-only values */
for (uint8_t i = 0U; i < param->num_cis; i++) {
const struct bt_iso_chan *cis = param->cis_channels[i];
const struct bt_iso_chan_qos *qos = cis->qos;
const struct bt_iso_chan_qos *qos;
if (cis == NULL || cis->qos == NULL) {
continue;
}
qos = cis->qos;
if (qos->num_subevents > 0U) {
return true;
@@ -1716,6 +1744,14 @@ static bool valid_cig_param(const struct bt_iso_cig_param *param, bool advanced,
return false;
}
/* Not guaranteed by all callers (bt_iso_cig_reconfigure does not pre-check
* it); the per-CIS loop below dereferences cis_channels[i] directly.
*/
if (param->cis_channels == NULL) {
LOG_ERR("CisChansNull");
return false;
}
if (param->num_cis > BT_ISO_MAX_GROUP_ISO_COUNT ||
param->num_cis > CONFIG_BT_ISO_MAX_CHAN) {
LOG_ERR("TooLargeNumCis[%u][%u]",
@@ -2509,17 +2545,32 @@ static bool is_advanced_big_param(const struct bt_iso_big_create_param *param)
return true;
}
/* This probe runs before valid_big_param(); guard structure here so
* caller misuse (NULL bis_channels/bis/qos/qos->tx, or an over-reported
* num_bis) falls through to that check's -EINVAL instead of a NULL or
* out-of-bounds deref in this probe.
*/
if (param->bis_channels == NULL ||
param->num_bis > BT_ISO_MAX_GROUP_ISO_COUNT ||
param->num_bis > CONFIG_BT_ISO_MAX_CHAN) {
return false;
}
/* Check if any of the CIS contain any test-param-only values */
for (uint8_t i = 0U; i < param->num_bis; i++) {
const struct bt_iso_chan *bis = param->bis_channels[i];
const struct bt_iso_chan_qos *qos = bis->qos;
const struct bt_iso_chan_qos *qos;
if (bis == NULL || bis->qos == NULL || bis->qos->tx == NULL) {
continue;
}
qos = bis->qos;
if (qos->num_subevents > 0U) {
return true;
}
assert(qos->tx != NULL && "BigWithNullTx");
if (qos->tx->max_pdu > 0U || qos->tx->burst_number > 0U) {
return true;
}
@@ -2543,6 +2594,17 @@ static bool valid_big_param(const struct bt_iso_big_create_param *param, bool ad
return false;
}
/* Bound num_bis before the per-BIS loop so a caller that over-reports it
* cannot drive the loop past the bis_channels[] array.
*/
CHECKIF(param->num_bis > BT_ISO_MAX_GROUP_ISO_COUNT ||
param->num_bis > CONFIG_BT_ISO_MAX_CHAN) {
LOG_ERR("TooLargeNumBis[%u][%u][%u]",
param->num_bis, BT_ISO_MAX_GROUP_ISO_COUNT, CONFIG_BT_ISO_MAX_CHAN);
return false;
}
for (uint8_t i = 0; i < param->num_bis; i++) {
struct bt_iso_chan *bis = param->bis_channels[i];
@@ -2586,14 +2648,6 @@ static bool valid_big_param(const struct bt_iso_big_create_param *param, bool ad
return false;
}
CHECKIF(param->num_bis > BT_ISO_MAX_GROUP_ISO_COUNT ||
param->num_bis > CONFIG_BT_ISO_MAX_CHAN) {
LOG_ERR("TooLargeNumBis[%u][%u]",
param->num_bis, MAX(CONFIG_BT_ISO_MAX_CHAN, BT_ISO_MAX_GROUP_ISO_COUNT));
return false;
}
CHECKIF(!IN_RANGE(param->interval, BT_ISO_SDU_INTERVAL_MIN, BT_ISO_SDU_INTERVAL_MAX)) {
LOG_ERR("InvInterval[%u]", param->interval);