Hello U-Boot maintainers,
I found a heap out-of-bounds read in the FWU v2 metadata initialization path.
Tested version
==============
U-Boot v2026.10-rc5
Commit: a06e89ab05eaa2b8344d521319399333cd760ae5
Affected configuration
======================
CONFIG_FWU_MULTI_BANK_UPDATE=y
CONFIG_FWU_MDATA_V2=y
CONFIG_FWU_NUM_BANKS=2
CONFIG_FWU_NUM_IMAGES_PER_BANK=2
Summary
=======
FWU v2 uses the metadata_size value read from persistent FWU metadata to
allocate heap storage for two metadata copies.
A metadata_size of 40 bytes contains the 32-byte top-level header and the
8-byte firmware-store descriptor header. It can therefore pass the version,
descriptor offset, CRC, bank count, and image count checks.
The metadata does not contain the image-entry array required by the configured
number of images. However, fwu_data_init() copies the entire image array whose
size is determined by the compile-time configuration. This results in a heap
out-of-bounds read.
Technical details
=================
lib/fwu_updates/fwu.c allocates storage for two copies using the metadata size:
int fwu_mdata_copies_allocate(u32 mdata_size)
{
...
g_fwu_data.fwu_mdata = calloc(2, mdata_size);
...
}
With metadata_size=40, the total allocation is 80 bytes.
lib/fwu_updates/fwu_v2.c compares the descriptor's bank and image counts with
the configured values:
num_banks = fwu_get_fw_desc(mdata)->num_banks;
num_images = fwu_get_fw_desc(mdata)->num_images;
if (num_banks != CONFIG_FWU_NUM_BANKS)
return -EINVAL;
if (num_images != CONFIG_FWU_NUM_IMAGES_PER_BANK)
return -EINVAL;
There is no check that metadata_size includes the corresponding
struct fwu_image_entry array.
fwu_data_init() subsequently performs this copy:
image_info_size = sizeof(data->fwu_images);
src_img_info = &fwu_get_fw_desc(mdata)->img_entry[0];
dst_img_info = &data->fwu_images[0];
memcpy(dst_img_info, src_img_info, image_info_size);
With two banks and two images, the relevant sizes are:
sizeof(struct fwu_mdata) = 32
descriptor header = 8
declared metadata_size = 40
allocation for two metadata copies = 80
sizeof(data->fwu_images) = 160
copy source offset = 40
bytes read beyond the allocation = 120
memcpy() reads 160 bytes beginning at allocation offset 40. The allocation
ends at offset 80, so the final 120 bytes are outside the heap object.
Reproduction
============
1. Build U-Boot with the configuration shown above.
2. Prepare both the primary and secondary FWU metadata copies with:
version = 2
metadata_size = 40
desc_offset = 32
num_banks = 2
num_images = 2
3. Set a valid CRC32 for the declared 40-byte metadata.
4. Store both copies in the configured FWU metadata locations.
5. Invoke fwu_init() through the normal FWU initialization path.
The mandatory-header, CRC, bank-count, and image-count checks pass.
fwu_data_init() then reads the missing image entries beyond the allocated
metadata storage.
ASan result
===========
top-level metadata size: 32
descriptor header size: 8
declared metadata size: 40
image copy size: 160
total allocation for two copies: 80
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 160
#0 memcpy
#1 fwu_data_init
lib/fwu_updates/fwu_v2.c:55
#2 fwu_init
lib/fwu_updates/fwu_v2.c:259
The read begins at allocation offset 40 and extends to offset 199.
The allocation ends at offset 80, resulting in a 120-byte over-read.
Impact
======
An attacker who can modify or supply FWU v2 metadata with a valid CRC can
trigger a heap out-of-bounds read while U-Boot initializes the metadata.
The confirmed impact is a bootloader crash or denial of service. Data located
after the allocation may also be copied into U-Boot's internal FWU image
information, although I have not demonstrated disclosure or control-flow
impact.
The issue is present in current main at the tested revision.
Regards,
Jaeyeong Lee