mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-15 13:40:01 +00:00
nimble/host: Fix possible overflow in ble_gatts_peer_cl_sup_feat_update
This function would write pass conn->bhc_gatt_svr.peer_cl_sup_feat buffer. Since supported features are likely to be small (currently only 3 bits are defined) lets keep this simple and just make local copy before validation.
This commit is contained in:
+28
-31
@@ -1613,8 +1613,9 @@ int
|
|||||||
ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om)
|
ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om)
|
||||||
{
|
{
|
||||||
struct ble_hs_conn *conn;
|
struct ble_hs_conn *conn;
|
||||||
|
uint8_t feat[BLE_GATT_CHR_CLI_SUP_FEAT_SZ] = {};
|
||||||
|
uint16_t len;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int feat_idx = 0;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
BLE_HS_LOG(DEBUG, "");
|
BLE_HS_LOG(DEBUG, "");
|
||||||
@@ -1623,46 +1624,42 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om)
|
|||||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* RFU bits are ignored so we can skip any bytes larger than supported */
|
||||||
|
len = os_mbuf_len(om);
|
||||||
|
if (len > BLE_GATT_CHR_CLI_SUP_FEAT_SZ) {
|
||||||
|
len = BLE_GATT_CHR_CLI_SUP_FEAT_SZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_mbuf_copydata(om, 0, len, feat) < 0) {
|
||||||
|
return BLE_ATT_ERR_UNLIKELY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear RFU bits */
|
||||||
|
for (i = 0; i < BLE_GATT_CHR_CLI_SUP_FEAT_SZ; i++) {
|
||||||
|
feat[i] &= (BLE_GATT_CHR_CLI_SUP_FEAT_MASK >> (8 * i));
|
||||||
|
}
|
||||||
|
|
||||||
ble_hs_lock();
|
ble_hs_lock();
|
||||||
conn = ble_hs_conn_find(conn_handle);
|
conn = ble_hs_conn_find(conn_handle);
|
||||||
if (conn == NULL) {
|
if (conn == NULL) {
|
||||||
rc = BLE_ATT_ERR_UNLIKELY;
|
rc = BLE_ATT_ERR_UNLIKELY;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (om->om_len == 0) {
|
|
||||||
/* Nothing to do */
|
|
||||||
goto done;
|
|
||||||
} else if (os_mbuf_len(om) > BLE_ATT_ATTR_MAX_LEN) {
|
|
||||||
rc = BLE_ATT_ERR_INSUFFICIENT_RES;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(om) {
|
/**
|
||||||
for (i = 0; i < om->om_len; i++) {
|
* Disabling already enabled features is not permitted
|
||||||
/**
|
* (Vol. 3, Part F, 3.3.3)
|
||||||
* Disabling already enabled features is not permitted
|
*/
|
||||||
* (Vol. 3, Part F, 3.3.3)
|
for (i = 0; i < BLE_GATT_CHR_CLI_SUP_FEAT_SZ; i++) {
|
||||||
* If value of saved octet, as uint8_t, is greatet than requested
|
if ((conn->bhc_gatt_svr.peer_cl_sup_feat[i] & feat[i]) !=
|
||||||
* it means more bits are set.
|
conn->bhc_gatt_svr.peer_cl_sup_feat[i]) {
|
||||||
*/
|
rc = BLE_ATT_ERR_VALUE_NOT_ALLOWED;
|
||||||
if (conn->bhc_gatt_svr.peer_cl_sup_feat[feat_idx] >
|
goto done;
|
||||||
om->om_data[i]) {
|
|
||||||
rc = BLE_ATT_ERR_VALUE_NOT_ALLOWED;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All RFU bits should be unset */
|
|
||||||
if (feat_idx == 0) {
|
|
||||||
om->om_data[i] &= BLE_GATT_CHR_CLI_SUP_FEAT_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->bhc_gatt_svr.peer_cl_sup_feat[feat_idx] |= om->om_data[i];
|
|
||||||
|
|
||||||
feat_idx++;
|
|
||||||
}
|
}
|
||||||
om = SLIST_NEXT(om, om_next);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(conn->bhc_gatt_svr.peer_cl_sup_feat, feat, BLE_GATT_CHR_CLI_SUP_FEAT_SZ);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
ble_hs_unlock();
|
ble_hs_unlock();
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
Reference in New Issue
Block a user