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 >
