fit_image_load_storage() repeats the data-position / data-offset / totalsize-alignment sequence that fit_image_get_data() performs, and writes the result through an int pointer where the getters expect a u32. The copy also omits the range check on the sum, so an offset that the embedded path rejects is accepted here.
Extract fit_image_ext_data_offset() and call it from both. The storage path gains the range check and both agree on one expression for the alignment. Signed-off-by: Daniel Golle <[email protected]> --- boot/image-fit.c | 82 ++++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index 6ab6c6c7da9..f02ac58d733 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -1056,6 +1056,47 @@ int fit_image_get_data_size_unciphered(const void *fit, int noffset, return 0; } +/** + * fit_image_ext_data_offset - locate a sub-image's external data + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @offsetp: holds the data offset from the start of the FIT, on success + * + * returns: + * 0, if the sub-image has external data + * -ENOENT, if its data is embedded in the FIT + * -EINVAL, if the recorded offset is out of range + */ +static int fit_image_ext_data_offset(const void *fit, int noffset, u32 *offsetp) +{ + size_t fdt_total_size_aligned; + u32 offset; + + if (!fit_image_get_data_position(fit, noffset, &offset)) { + *offsetp = offset; + + return 0; + } + + if (fit_image_get_data_offset(fit, noffset, &offset)) + return -ENOENT; + + /* + * data-offset counts from the end of the FDT, so that is the base for + * every image; the sum has to stay within a u32. + */ + fdt_total_size_aligned = ALIGN(fdt_totalsize(fit), 4); + if (fdt_total_size_aligned > UINT32_MAX - offset) { + printf("Invalid external data offset: %u\n", offset); + + return -EINVAL; + } + + *offsetp = offset + fdt_total_size_aligned; + + return 0; +} + /** * fit_image_get_data - get data and its size including * both embedded and external data @@ -1077,29 +1118,14 @@ int fit_image_get_data(const void *fit, int noffset, const void **data, { bool external_data = false; int ret; - size_t fdt_total_size_aligned; u32 offset; u32 len; uintptr_t max_offset; - if (!fit_image_get_data_position(fit, noffset, &offset)) { - external_data = true; - } else if (!fit_image_get_data_offset(fit, noffset, &offset)) { - /* - * For FIT with external data, figure out where - * the external images start. This is the base - * for the data-offset properties in each image. - */ - fdt_total_size_aligned = ((fdt_totalsize(fit) + 3) & ~3); - /* The resulting offset cannot exceed UINT32_MAX */ - if (fdt_total_size_aligned > UINT32_MAX - offset) { - printf("Invalid external data offset: %u\n", offset); - return -EINVAL; - } - offset += fdt_total_size_aligned; - - external_data = true; - } + ret = fit_image_ext_data_offset(fit, noffset, &offset); + if (ret && ret != -ENOENT) + return ret; + external_data = !ret; if (external_data) { debug("External Data\n"); @@ -2185,12 +2211,12 @@ static int fit_image_load_storage(struct bootm_headers *images, const void *fit, int noffset, enum fit_load_op load_op, ulong *datap, ulong *lenp, bool *early) { - int data_off = 0, data_sz = 0; - bool external = false; + u32 data_off = 0, data_sz = 0; ulong img_load; u8 img_comp = IH_COMP_NONE; void *mapped; void *dst; + int ret; if (CONFIG_IS_ENABLED(FIT_VERITY)) { u8 img_type; @@ -2207,19 +2233,13 @@ static int fit_image_load_storage(struct bootm_headers *images, const void *fit, } } - if (!fit_image_get_data_position(fit, noffset, &data_off)) { - external = true; - } else if (!fit_image_get_data_offset(fit, noffset, &data_off)) { - external = true; - data_off += ALIGN(fdt_totalsize(fit), 4); - } + ret = fit_image_ext_data_offset(fit, noffset, &data_off); + if (ret) + return ret == -ENOENT ? 0 : ret; - if (!external || fit_image_get_data_size(fit, noffset, &data_sz)) + if (fit_image_get_data_size(fit, noffset, &data_sz)) return 0; - if (data_off < 0 || data_sz < 0) - return -EINVAL; - fit_image_get_comp(fit, noffset, &img_comp); if (img_comp == IH_COMP_NONE && load_op != FIT_LOAD_IGNORED && -- 2.56.0
