mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(ble_mesh): validate PB-ADV start segment length
(cherry picked from commit 912ec8dc62)
Co-authored-by: luoxu <luoxu@espressif.com>
This commit is contained in:
@@ -188,6 +188,8 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
|||||||
struct net_buf_simple *buf,
|
struct net_buf_simple *buf,
|
||||||
struct prov_rx *rx, bool *close)
|
struct prov_rx *rx, bool *close)
|
||||||
{
|
{
|
||||||
|
uint8_t last_seg = START_LAST_SEG(rx->gpc);
|
||||||
|
|
||||||
if (link->rx.seg) {
|
if (link->rx.seg) {
|
||||||
BT_INFO("Get Start while there are unreceived segments");
|
BT_INFO("Get Start while there are unreceived segments");
|
||||||
return false;
|
return false;
|
||||||
@@ -215,7 +217,7 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
|||||||
link->rx.fcs = net_buf_simple_pull_u8(buf);
|
link->rx.fcs = net_buf_simple_pull_u8(buf);
|
||||||
|
|
||||||
BT_DBG("LinkId:%08x,len %u last_seg %u total_len %u fcs 0x%02x", link->link_id, buf->len,
|
BT_DBG("LinkId:%08x,len %u last_seg %u total_len %u fcs 0x%02x", link->link_id, buf->len,
|
||||||
START_LAST_SEG(rx->gpc), link->rx.buf->len, link->rx.fcs);
|
last_seg, link->rx.buf->len, link->rx.fcs);
|
||||||
|
|
||||||
/* At least one-octet pdu type is needed */
|
/* At least one-octet pdu type is needed */
|
||||||
if (link->rx.buf->len < 1) {
|
if (link->rx.buf->len < 1) {
|
||||||
@@ -226,8 +228,8 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (START_LAST_SEG(rx->gpc) > START_LAST_SEG_MAX) {
|
if (last_seg > START_LAST_SEG_MAX) {
|
||||||
BT_ERR("Invalid SegN 0x%02x", START_LAST_SEG(rx->gpc));
|
BT_ERR("Invalid SegN 0x%02x", last_seg);
|
||||||
if (close) {
|
if (close) {
|
||||||
*close = true;
|
*close = true;
|
||||||
}
|
}
|
||||||
@@ -243,16 +245,19 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (START_LAST_SEG(rx->gpc) > 0) {
|
/* Validate that the declared total length and the actual start-segment
|
||||||
/* For multi-segment PDUs, validate that total length is consistent
|
* payload length match the claimed segment count before copying segment 0.
|
||||||
* with the claimed segment count to prevent underflow in
|
* This keeps malformed extended advertising reports from writing past the
|
||||||
* bt_mesh_gen_prov_cont() when computing expect_len.
|
* fixed provisioning rx buffer.
|
||||||
* Minimum length = first segment (20) + (last_seg - 1) * full continuation (23) + 1
|
*/
|
||||||
|
if (last_seg > 0) {
|
||||||
|
/* Minimum length = first segment (20) + (last_seg - 1) *
|
||||||
|
* full continuation (23) + one byte in the last segment.
|
||||||
*/
|
*/
|
||||||
uint16_t min_len = 20 + 23 * (START_LAST_SEG(rx->gpc) - 1) + 1;
|
uint16_t min_len = START_PAYLOAD_MAX + CONT_PAYLOAD_MAX * (last_seg - 1) + 1;
|
||||||
if (link->rx.buf->len < min_len) {
|
if (link->rx.buf->len < min_len) {
|
||||||
BT_ERR("Total length %u too small for %u segments (min %u)",
|
BT_ERR("Total length %u too small for %u segments (min %u)",
|
||||||
link->rx.buf->len, START_LAST_SEG(rx->gpc) + 1, min_len);
|
link->rx.buf->len, last_seg + 1, min_len);
|
||||||
if (close) {
|
if (close) {
|
||||||
*close = true;
|
*close = true;
|
||||||
}
|
}
|
||||||
@@ -260,8 +265,30 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
link->rx.seg = (1 << (START_LAST_SEG(rx->gpc) + 1)) - 1;
|
{
|
||||||
link->rx.last_seg = START_LAST_SEG(rx->gpc);
|
uint16_t max_len = START_PAYLOAD_MAX + CONT_PAYLOAD_MAX * last_seg;
|
||||||
|
uint16_t seg_0_len = last_seg ? START_PAYLOAD_MAX : link->rx.buf->len;
|
||||||
|
|
||||||
|
if (link->rx.buf->len > max_len) {
|
||||||
|
BT_ERR("Total length %u too large for %u segments (max %u)",
|
||||||
|
link->rx.buf->len, last_seg + 1, max_len);
|
||||||
|
if (close) {
|
||||||
|
*close = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf->len != seg_0_len) {
|
||||||
|
BT_ERR("Invalid start segment len %u != %u", buf->len, seg_0_len);
|
||||||
|
if (close) {
|
||||||
|
*close = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
link->rx.seg = (1 << (last_seg + 1)) - 1;
|
||||||
|
link->rx.last_seg = last_seg;
|
||||||
memcpy(link->rx.buf->data, buf->data, buf->len);
|
memcpy(link->rx.buf->data, buf->data, buf->len);
|
||||||
XACT_SEG_RECV(link, 0);
|
XACT_SEG_RECV(link, 0);
|
||||||
BT_DBG("Seg: %04x, lastSeg: %04x, Data: %s", link->rx.seg, link->rx.last_seg, bt_hex(buf->data, buf->len));
|
BT_DBG("Seg: %04x, lastSeg: %04x, Data: %s", link->rx.seg, link->rx.last_seg, bt_hex(buf->data, buf->len));
|
||||||
|
|||||||
Reference in New Issue
Block a user