[PATCH] reloc_bootstage: Fix out-of-bounds read

Simon Glass sjg at chromium.org
Sat Jul 13 17:13:50 CEST 2024


Hi Richard,

On Fri, 12 Jul 2024 at 09:11, Richard Weinberger <richard at nod.at> wrote:
>
> bootstage_get_size() returns the total size of the data structure
> including associated records.
> When copying from gd->bootstage, only the allocation size of gd->bootstage
> must be used. Otherwise too much memory is copied.
>
> This bug caused no harm so far because gd->new_bootstage is always
> large enough and reading beyond the allocation length of gd->bootstage
> caused no problem due to the U-Boot memory layout.
>
> Fix by using the correct size and perform the initial copy directly
> in bootstage_relocate() to have the whole relocation process in the
> same function.

Nice commit message.

Can you use 'bootstage' as the commit tag?

>
> Signed-off-by: Richard Weinberger <richard at nod.at>
> ---
>  common/board_f.c   | 6 ------
>  common/bootstage.c | 7 ++++++-
>  2 files changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/common/board_f.c b/common/board_f.c
> index 039d6d712d..f4d87692b9 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -683,12 +683,6 @@ static int reloc_bootstage(void)
>         if (gd->flags & GD_FLG_SKIP_RELOC)
>                 return 0;
>         if (gd->new_bootstage) {
> -               int size = bootstage_get_size();
> -
> -               debug("Copying bootstage from %p to %p, size %x\n",
> -                     gd->bootstage, gd->new_bootstage, size);
> -               memcpy(gd->new_bootstage, gd->bootstage, size);
> -               gd->bootstage = gd->new_bootstage;
>                 bootstage_relocate();
>         }
>  #endif
> diff --git a/common/bootstage.c b/common/bootstage.c
> index 0e6d80718f..aea5a318df 100644
> --- a/common/bootstage.c
> +++ b/common/bootstage.c
> @@ -58,10 +58,15 @@ struct bootstage_hdr {
>
>  int bootstage_relocate(void)
>  {
> -       struct bootstage_data *data = gd->bootstage;
> +       struct bootstage_data *data;
>         int i;
>         char *ptr;
>
> +       debug("Copying bootstage from %p to %p\n", gd->bootstage,
> +             gd->new_bootstage);
> +       memcpy(gd->new_bootstage, gd->bootstage, sizeof(struct bootstage_data));

I would like to have the relocation addresses in board_f like with
other relocations, so it is easy to see what is happening, in one
file. So how about passing the old address to bootstage_relocate() so
it doesn't need to access gd->new_bootstage ?

> +       data = gd->bootstage = gd->new_bootstage;
> +
>         /* Figure out where to relocate the strings to */
>         ptr = (char *)(data + 1);
>
> --
> 2.35.3
>

Regards,
Simon


More information about the U-Boot mailing list