mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
fix(ble_mesh): added internal buffer to store dfu targets
The protocol may still receive DFU-related packets from the
network (such as forwarded or retransmitted ones) after DFU ends,
while the user might release the targets immediately after DFU completion.
However, since the list head is not empty, the protocol could access
already-freed memory when iterating through the targets.
(cherry picked from commit 8c8b43f564)
Co-authored-by: luoxu <luoxu@espressif.com>
This commit is contained in:
@@ -73,7 +73,8 @@ esp_err_t esp_ble_mesh_dfu_cli_img_send(esp_ble_mesh_dfu_cli_t *cli,
|
||||
arg.send_arg.xfer = xfer;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_dfu_client_args_t),
|
||||
NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
btc_ble_mesh_dfu_client_arg_deep_copy,
|
||||
btc_ble_mesh_dfu_client_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
uint8_t esp_ble_mesh_dfu_cli_progress(esp_ble_mesh_dfu_cli_t *cli)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -81,6 +81,11 @@ void btc_ble_mesh_dfu_client_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_BLE_MESH_ACT_DFU_CLIENT_IMG_SEND:
|
||||
/* That will be freed when dfu completed or failed not on btc deep free */
|
||||
dst->send_arg.inputs =(struct esp_ble_mesh_blob_cli_inputs *)
|
||||
dfu_targets_alloc((struct bt_mesh_blob_cli_inputs *)src->send_arg.inputs);
|
||||
break;
|
||||
default:
|
||||
BT_DBG("%s, Unknown act %d", __func__, msg->act);
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Nordic Semiconductor ASA
|
||||
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -64,6 +64,83 @@ static struct {
|
||||
sys_slist_t list;
|
||||
} dfu_req_list;
|
||||
|
||||
static struct bt_mesh_blob_cli_inputs cur_targets = {0};
|
||||
|
||||
/**
|
||||
* inputs list must point to a list of bt_mesh_dfu_target nodes.
|
||||
* That was required by dfu api
|
||||
*/
|
||||
void dfu_targets_free(void)
|
||||
{
|
||||
sys_snode_t *n, *sn;
|
||||
struct bt_mesh_dfu_target *target;
|
||||
struct bt_mesh_blob_cli_inputs *inputs = &cur_targets;
|
||||
|
||||
if (cur_targets.targets.head == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
SYS_SLIST_FOR_EACH_NODE_SAFE(&inputs->targets, n, sn) {
|
||||
target = (struct bt_mesh_dfu_target *)n;
|
||||
if (target->blob.pull) {
|
||||
bt_mesh_free(target->blob.pull);
|
||||
}
|
||||
bt_mesh_free(target);
|
||||
}
|
||||
|
||||
inputs->app_idx = 0;
|
||||
inputs->group = 0;
|
||||
inputs->ttl = 0;
|
||||
inputs->timeout_base = 0;
|
||||
|
||||
sys_slist_init(&inputs->targets);
|
||||
}
|
||||
|
||||
struct bt_mesh_blob_cli_inputs *dfu_targets_alloc(struct bt_mesh_blob_cli_inputs *src)
|
||||
{
|
||||
sys_snode_t *node;
|
||||
struct bt_mesh_dfu_target *target_src = NULL;
|
||||
struct bt_mesh_dfu_target *target_dst = NULL;
|
||||
struct bt_mesh_blob_cli_inputs *dst = &cur_targets;
|
||||
|
||||
if (cur_targets.targets.head != NULL ||
|
||||
cur_targets.targets.tail != NULL) {
|
||||
BT_WARN("DFU targets busy");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dst->app_idx = src->app_idx;
|
||||
dst->group = src->group;
|
||||
dst->ttl = src->ttl;
|
||||
dst->timeout_base = src->timeout_base;
|
||||
|
||||
sys_slist_init(&dst->targets);
|
||||
|
||||
SYS_SLIST_FOR_EACH_NODE(&src->targets, node) {
|
||||
target_src = (struct bt_mesh_dfu_target *)node;
|
||||
target_dst = bt_mesh_calloc(sizeof(struct bt_mesh_dfu_target));
|
||||
if (!target_dst) {
|
||||
dfu_targets_free();
|
||||
return NULL;
|
||||
}
|
||||
memcpy(target_dst, target_src, sizeof(struct bt_mesh_dfu_target));
|
||||
if (target_dst->blob.pull) {
|
||||
target_dst->blob.pull = bt_mesh_calloc(sizeof(struct bt_mesh_blob_target_pull));
|
||||
if (!target_dst->blob.pull) {
|
||||
dfu_targets_free();
|
||||
return NULL;
|
||||
}
|
||||
memcpy(target_dst->blob.pull, target_src->blob.pull, sizeof(struct bt_mesh_blob_target_pull));
|
||||
} else {
|
||||
target_dst->blob.pull = NULL;
|
||||
}
|
||||
target_dst->blob.n.next = NULL;
|
||||
sys_slist_append(&dst->targets, &target_dst->blob.n);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static struct bt_mesh_dfu_target *target_get(struct bt_mesh_dfu_cli *cli,
|
||||
uint16_t addr)
|
||||
{
|
||||
@@ -277,6 +354,8 @@ static void dfu_failed(struct bt_mesh_dfu_cli *cli,
|
||||
if (cli->cb && cli->cb->ended) {
|
||||
cli->cb->ended(cli, reason);
|
||||
}
|
||||
|
||||
dfu_targets_free();
|
||||
}
|
||||
|
||||
static int req_setup(struct bt_mesh_dfu_cli *cli, enum req type,
|
||||
@@ -839,6 +918,7 @@ static void confirmed(struct bt_mesh_blob_cli *b)
|
||||
if (cli->cb && cli->cb->confirmed) {
|
||||
cli->cb->confirmed(cli);
|
||||
}
|
||||
dfu_targets_free();
|
||||
} else {
|
||||
dfu_failed(cli, BLE_MESH_DFU_ERR_INTERNAL);
|
||||
}
|
||||
@@ -1202,6 +1282,12 @@ static void dfu_cli_reset(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct bt_mesh_dfu_cli *cli = mod->user_data;
|
||||
|
||||
if (cli->xfer.state == STATE_IDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
dfu_targets_free();
|
||||
|
||||
bt_mesh_dfu_req_list_free();
|
||||
cli->req = NULL;
|
||||
cli->xfer.state = STATE_IDLE;
|
||||
|
||||
@@ -261,6 +261,9 @@ struct bt_mesh_dfu_cli_xfer {
|
||||
const struct bt_mesh_dfu_cli_xfer_blob_params *blob_params;
|
||||
};
|
||||
|
||||
void dfu_targets_free(void);
|
||||
struct bt_mesh_blob_cli_inputs *dfu_targets_alloc(struct bt_mesh_blob_cli_inputs *src);
|
||||
|
||||
/** @brief Start distributing a DFU.
|
||||
*
|
||||
* Starts distribution of the firmware in the given slot to the list of DFU
|
||||
|
||||
Reference in New Issue
Block a user