ext: lib: mcumgr: Fix slot-1 image upload deadlock condition

If a firmware update is attempted with a corrupt image and a power outage or
reset occurs while the bootloader (mcubooot v3.1 in this case) is erasing the
corrupt image then slot-1 can be left in a state where mcuboot has not
properly released slot-1 and a DFU transfer can no longer happen.  Attempts
to upload will transfer 0 bytes as the trailer at the end of the slot remains
present and indicates the slot is 'in use' blocking the slot erase operation
on reception of the 1st image block or a image erase command.

This commit fixes this issue by adding a addition requirement that a slot is
'in use'.   The additional requirement is that the image header magic value
located at the beginning of the slot is also present.  If this additional
requirement is not also met then the slot is considered not 'in use'.

Signed-off-by: Nick Ward <nick.ward@setec.com.au>
This commit is contained in:
Nick Ward 2020-07-08 20:20:14 +10:00 committed by Anas Nashif
parent 17e2618f2f
commit 4c1c1732ed
3 changed files with 33 additions and 7 deletions

View File

@ -237,8 +237,14 @@ img_mgmt_erase(struct mgmt_ctxt *ctxt)
{
CborError err;
int rc;
bool slot1_in_use;
if (img_mgmt_slot_in_use(1)) {
rc = img_mgmt_slot_in_use(1, &slot1_in_use);
if (rc != 0) {
return rc;
}
if (slot1_in_use) {
/* No free slot. */
return MGMT_ERR_EBADSTATE;
}
@ -307,8 +313,14 @@ img_mgmt_upload_first_chunk(struct mgmt_ctxt *ctxt, const uint8_t *req_data,
size_t data_sha_len)
{
int rc;
bool slot1_in_use;
if (img_mgmt_slot_in_use(1)) {
rc = img_mgmt_slot_in_use(1, &slot1_in_use);
if (rc != 0) {
return rc;
}
if (slot1_in_use) {
/* No free slot. */
return MGMT_ERR_ENOMEM;
}

View File

@ -84,7 +84,7 @@ int img_mgmt_find_by_hash(uint8_t *find, struct image_version *ver);
int img_mgmt_find_by_ver(struct image_version *find, uint8_t *hash);
int img_mgmt_read_info(int image_slot, struct image_version *ver,
uint8_t *hash, uint32_t *flags);
int img_mgmt_slot_in_use(int slot);
int img_mgmt_slot_in_use(int slot, bool *in_use);
int img_mgmt_state_read(struct mgmt_ctxt *ctxt);
int img_mgmt_state_write(struct mgmt_ctxt *njb);
int img_mgmt_ver_str(const struct image_version *ver, char *dst);

View File

@ -108,14 +108,28 @@ img_mgmt_state_any_pending(void)
* the slot can be freely erased.
*/
int
img_mgmt_slot_in_use(int slot)
img_mgmt_slot_in_use(int slot, bool *in_use)
{
uint8_t state_flags;
struct image_header hdr;
int rc;
state_flags = img_mgmt_state_flags(slot);
return state_flags & IMG_MGMT_STATE_F_ACTIVE ||
state_flags & IMG_MGMT_STATE_F_CONFIRMED ||
state_flags & IMG_MGMT_STATE_F_PENDING;
*in_use = state_flags & IMG_MGMT_STATE_F_ACTIVE ||
state_flags & IMG_MGMT_STATE_F_CONFIRMED ||
state_flags & IMG_MGMT_STATE_F_PENDING;
/* Check validity of in_use state by checking the image header contains
* the magic value.
*/
rc = img_mgmt_impl_read(slot, 0, &hdr, sizeof hdr);
if (hdr.ih_magic != IMAGE_MAGIC) {
/* Image is invalid */
*in_use = false;
}
return rc;
}
/**