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

Reply via email to