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>
This commit is contained in:
Lijo Lazar
2026-06-16 10:14:58 +05:30
committed by Alex Deucher
parent 230753e46a
commit be88697602
3 changed files with 23 additions and 7 deletions

View File

@@ -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;

View File

@@ -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");

View File

@@ -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);