On Tue, Jun 16, 2026 at 1:28 AM Lijo Lazar <[email protected]> wrote:
>
> atom_index_iio() parsed the IIO bytecode without bounds checks, allowing
> out-of-bounds reads on a malformed VBIOS. Pass the BIOS size into
> amdgpu_atom_parse() and bound the parse loops by it.
>
> Signed-off-by: Lijo Lazar <[email protected]>
> Assisted-by: Claude Code

Reviewed-by: Alex Deucher <[email protected]>

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c |  2 +-
>  drivers/gpu/drm/amd/amdgpu/atom.c            | 21 +++++++++++++++-----
>  drivers/gpu/drm/amd/amdgpu/atom.h            |  3 ++-
>  3 files changed, 19 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
> index ca65e6ebdb25..a0c740bce310 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
> @@ -1923,7 +1923,7 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
>         atom_card_info->pll_read = cail_pll_read;
>         atom_card_info->pll_write = cail_pll_write;
>
> -       adev->mode_info.atom_context = amdgpu_atom_parse(atom_card_info, 
> adev->bios);
> +       adev->mode_info.atom_context = amdgpu_atom_parse(atom_card_info, 
> adev->bios, adev->bios_size);
>         if (!adev->mode_info.atom_context) {
>                 amdgpu_atombios_fini(adev);
>                 return -ENOMEM;
> diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c 
> b/drivers/gpu/drm/amd/amdgpu/atom.c
> index a40ce7555f28..941941cc1759 100644
> --- a/drivers/gpu/drm/amd/amdgpu/atom.c
> +++ b/drivers/gpu/drm/amd/amdgpu/atom.c
> @@ -1327,11 +1327,21 @@ static void atom_index_iio(struct atom_context *ctx, 
> int base)
>         ctx->iio = kzalloc(2 * 256, GFP_KERNEL);
>         if (!ctx->iio)
>                 return;
> -       while (CU8(base) == ATOM_IIO_START) {
> -               ctx->iio[CU8(base + 1)] = base + 2;
> +       while (base + 1 < ctx->bios_size && CU8(base) == ATOM_IIO_START) {
> +               uint8_t index = CU8(base + 1);
> +
> +               ctx->iio[index] = base + 2;
>                 base += 2;
> -               while (CU8(base) != ATOM_IIO_END)
> -                       base += atom_iio_len[CU8(base)];
> +               while (base < ctx->bios_size && CU8(base) != ATOM_IIO_END) {
> +                       uint8_t op = CU8(base);
> +
> +                       if (op >= ARRAY_SIZE(atom_iio_len)) {
> +                               /* Malformed table: mark method undefined */
> +                               ctx->iio[index] = 0;
> +                               return;
> +                       }
> +                       base += atom_iio_len[op];
> +               }
>                 base += 3;
>         }
>  }
> @@ -1553,7 +1563,7 @@ static inline void atom_print_vbios_info(struct 
> atom_context *ctx)
>                 drm_info(ctx->card->dev, "ATOM BIOS: %s\n", vbios_info);
>  }
>
> -struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios)
> +struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios, 
> uint32_t bios_size)
>  {
>         int base;
>         struct atom_context *ctx =
> @@ -1567,6 +1577,7 @@ struct atom_context *amdgpu_atom_parse(struct card_info 
> *card, void *bios)
>
>         ctx->card = card;
>         ctx->bios = bios;
> +       ctx->bios_size = bios_size;
>
>         if (CU16(0) != ATOM_BIOS_MAGIC) {
>                 pr_info("Invalid BIOS magic\n");
> diff --git a/drivers/gpu/drm/amd/amdgpu/atom.h 
> b/drivers/gpu/drm/amd/amdgpu/atom.h
> index bb3d9eb7eb6b..4687c019cbe3 100644
> --- a/drivers/gpu/drm/amd/amdgpu/atom.h
> +++ b/drivers/gpu/drm/amd/amdgpu/atom.h
> @@ -133,6 +133,7 @@ struct atom_context {
>         struct card_info *card;
>         struct mutex mutex;
>         void *bios;
> +       uint32_t bios_size;
>         uint32_t cmd_table, data_table;
>         uint16_t *iio;
>
> @@ -160,7 +161,7 @@ struct atom_context {
>
>  extern int amdgpu_atom_debug;
>
> -struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios);
> +struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios, 
> uint32_t bios_size);
>  int amdgpu_atom_execute_table(struct atom_context *ctx, int index, uint32_t 
> *params, int params_size);
>  int amdgpu_atom_asic_init(struct atom_context *ctx);
>  void amdgpu_atom_destroy(struct atom_context *ctx);
> --
> 2.49.0
>

Reply via email to