fit_image_get_data_offset(), fit_image_get_data_position() and
fit_image_get_data_size() pass NULL as fdt_getprop()'s length argument,
so they accept a property of any size and then dereference the first
four bytes of it. A property shorter than that is read past its end, and
the bytes that follow it in the FIT are returned to the caller. An empty
data-size, for example, is read as the structure tag that follows it, a
small number such as 2 or 3, and selects a few bytes of the external
data instead of failing.

Ask for the length and require it to be exactly one fdt32_t, as
commit c2b8eefd4e10 ("image-fit: check the length of the
data-size-unciphered property") does for data-size-unciphered. Every
caller already checks the return value and handles a failure like a
missing property.

Fixes: db1b79b886f0 ("splash: add support for loading splash from a FIT image")
Fixes: a1be94b65410 ("SPL: Add FIT data-position property support")
Signed-off-by: Aristo Chen <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
---
v2: no code changes, collected Reviewed-by

 boot/image-fit.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/boot/image-fit.c b/boot/image-fit.c
index 6ab6c6c7da9..fd625fe9a98 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -963,15 +963,20 @@ int fit_image_get_emb_data(const void *fit, int noffset, 
const void **data,
  * returns:
  *     0, on success
  *     -ENOENT if the property could not be found
+ *     -EINVAL if the property is not exactly one fdt32_t long
  */
 int fit_image_get_data_offset(const void *fit, int noffset, u32 *data_offset)
 {
        const fdt32_t *val;
+       int len;
 
-       val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL);
+       val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, &len);
        if (!val)
                return -ENOENT;
 
+       if (len != sizeof(*val))
+               return -EINVAL;
+
        *data_offset = fdt32_to_cpu(*val);
 
        return 0;
@@ -987,16 +992,21 @@ int fit_image_get_data_offset(const void *fit, int 
noffset, u32 *data_offset)
  * returns:
  *     0, on success
  *     -ENOENT if the property could not be found
+ *     -EINVAL if the property is not exactly one fdt32_t long
  */
 int fit_image_get_data_position(const void *fit, int noffset,
                                u32 *data_position)
 {
        const fdt32_t *val;
+       int len;
 
-       val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL);
+       val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, &len);
        if (!val)
                return -ENOENT;
 
+       if (len != sizeof(*val))
+               return -EINVAL;
+
        *data_position = fdt32_to_cpu(*val);
 
        return 0;
@@ -1012,15 +1022,20 @@ int fit_image_get_data_position(const void *fit, int 
noffset,
  * returns:
  *     0, on success
  *     -ENOENT if the property could not be found
+ *     -EINVAL if the property is not exactly one fdt32_t long
  */
 int fit_image_get_data_size(const void *fit, int noffset, u32 *data_size)
 {
        const fdt32_t *val;
+       int len;
 
-       val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL);
+       val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, &len);
        if (!val)
                return -ENOENT;
 
+       if (len != sizeof(*val))
+               return -EINVAL;
+
        *data_size = fdt32_to_cpu(*val);
 
        return 0;
-- 
2.43.0

Reply via email to