[PATCH v1 1/2] spl: fit: bound the external data size before reading it

Simon Glass sjg at chromium.org
Thu Jun 25 10:04:03 CEST 2026


Hi Aristo,

On 2026-06-18T15:47:45, Aristo Chen <aristo.chen at canonical.com> wrote:
> spl: fit: bound the external data size before reading it
>
> load_simple_fit() loads an image stored as external data by reading it
> from the boot device with a transfer sized from the FIT data-size
> property. That property is listed in exc_prop[] in image-fit-sig.c, so
> it is excluded from the configuration signature and stays under the
> control of anyone able to modify the boot medium even when
> CONFIG_SPL_FIT_SIGNATURE is enabled. The read happens before
> fit_image_verify_with_data() checks the image hash, so an inflated
> data-size overruns the destination before the corruption can be
> detected. The device-tree overlay path is the sharpest case, because
> there the destination is a fixed CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ
> heap buffer.
>
> Pass the size of the destination into load_simple_fit() and reject an
> image whose data does not fit before the read is issued. The data-size
> property is read into an int, so a value with bit 31 set arrives as a
> negative number, and comparing it as an unsigned quantity rejects that
> case as well. The block-aligned transfer length is checked too, because
> info->read() moves data-size rounded up to the device block length.
> [...]
>
> common/spl/spl_fit.c | 41 +++++++++++++++++++++++++++++++++++------
>  1 file changed, 35 insertions(+), 6 deletions(-)

> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> @@ -291,6 +294,18 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
> +             if ((ulong)len > max_size)
> +                     goto too_big;
> +

> @@ -302,6 +317,15 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
> +             /* The block-aligned read size must also fit the destination */
> +             if (size > max_size) {
> +too_big:
> +                     printf("%s: FIT image too large (max %lu)\n",
> +                            __func__, max_size);
> +                     return -EFBIG;
> +             }

Please can you avoid jumping into the body of an if-statement. A goto
landing inside a conditional block and falling through the printf and
return is hard to follow, and will likely trip up static analysers.
Put the shared label at the end of the function:

    if ((ulong)len > max_size)
        goto too_big;
    ...
    if (size > max_size)
        goto too_big;
    ...
    return 0;
    too_big:
        printf(...);
        return -EFBIG;

The cover letter quotes 57 bytes for the current shape; what does the
cleaner form cost on am335x_hs_evm? If it really does push past
CONFIG_SPL_MAX_SIZE then we'll have to use your code, but please say
so in the commit message.

> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> @@ -291,6 +294,18 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
> +             if ((ulong)len > max_size)
> +                     goto too_big;

Since size is the block-aligned length and size >= len, the second
check already covers everything this one catches, including the
negative-len case. The value of the early check is that it bails
before get_aligned_image_size() runs on a hostile value - please
mention that in the comment rather than the bit-31 reasoning, which
applies equally to the later check.

Also, the diagnostic only prints max_size. Including len (or size)
would make a real failure much easier to triage from a board log.

> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> @@ -427,7 +451,8 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image,
>       } else {
> -             ret = load_simple_fit(info, offset, ctx, node, &image_info);
> +             ret = load_simple_fit(info, offset, ctx, node, &image_info,
> +                                   CONFIG_SYS_BOOTM_LEN);

Just to check - the destination here is image_info.load_addr, set a
few lines up to ALIGN(spl_image->load_addr + spl_image->size, 8)  --
CONFIG_SYS_BOOTM_LEN is a sensible upper bound for the overall image,
but it isn't the space available at that address; the FDT is just
placed after the loaded image. Please note in the commit message that
for the non-overlay paths this is a conservative ceiling rather than
the true destination size, so it isn't mistaken for a tight bound
later. The overlay caller is the one actually sized to the buffer.

Regards,
Simon


More information about the U-Boot mailing list