mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-23 15:26:50 -04:00
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:
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user