diff options
| author | Lijo Lazar <lijo.lazar@amd.com> | 2026-06-16 10:14:58 +0530 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-07-01 11:14:50 -0400 |
| commit | be88697602238c3dcb47bbc2db1eef923f63e78b (patch) | |
| tree | d428d8b98e12147992ed169c4f37e508ffaf90e8 /drivers/gpu/drm/amd/amdgpu | |
| parent | 230753e46a4a9d04dad6a9b5dbaeb7fd52add7d0 (diff) | |
| download | linux-next-be88697602238c3dcb47bbc2db1eef923f63e78b.tar.gz linux-next-be88697602238c3dcb47bbc2db1eef923f63e78b.zip | |
drm/amdgpu: bounds check ATOM IIO table parsing
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 <lijo.lazar@amd.com>
Assisted-by: Claude Code
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Asad Kamal <asad.kamal@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/atom.c | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/atom.h | 3 |
3 files changed, 23 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index acd22bff1882..27c0dc8f6137 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 ca5d091549e1..c3824934ac7d 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.c +++ b/drivers/gpu/drm/amd/amdgpu/atom.c @@ -1327,11 +1327,25 @@ 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); + int start = 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); + + /* + * Unknown opcode: its length is unknown so the byte + * stream cannot be resynced reliably. + */ + if (op >= ARRAY_SIZE(atom_iio_len)) + return; + base += atom_iio_len[op]; + } + if (base >= ctx->bios_size) + return; + /* Only index well-formed methods, others stay 0 */ + ctx->iio[index] = start; base += 3; } } @@ -1553,7 +1567,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 +1581,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); |
